On Wed, 8 Sept 2021 at 16:10, Andreas Hennings <andr...@dqxtech.net> wrote:
>
> Thanks for the feedback so far!
>
> On Wed, 8 Sept 2021 at 10:13, Marco Pivetta <ocram...@gmail.com> wrote:
> >
> > Heyo,
> >
> > On Wed, 8 Sep 2021, 02:19 Andreas Hennings, <andr...@dqxtech.net> wrote:
> >>
> >> Hello internals,
> >>
> >> The function array_column() would be much more useful if there was an
> >> option to preserve the original array keys.
> >> I can create an RFC, but I think it is better to first discuss the options.
> >
> >
> > New function, please 🙏
>
> I am not opposed. But I am also curious what others think.
> What I don't like so much is how the situation with two different
> functions will have a "historically grown wtf" smell about it.
> But this is perhaps preferable to BC breaks or overly "magic"
> parameters or overly crowded signatures.
>
> If we go for a new function:
> A name could be array_column_assoc().
>
> array_column_assoc(array $array, string $value_key)
>
> This would behave the same as array_column($array, $value_key), but
> preserve original keys.
> Items which are not arrays or which lack the key will be omitted.
> A $value_key === NULL would be useless, because this would simply
> return the original array.
>
> The question is, should it do anything beyond the most obvious?
> Or should we leave it minimal for now, with the potential for
> additional parameters in the future?
>
> Limitations:
> If some items are omitted, it will be awkward to restore the missing
> items while preserving the order of the array.
>
> Possible ideas for additional functionality:
> - Replicate a lot of the behavior of array_column(), e.g. with an
> optional $index_key parameter. This would be mostly redundant.
> - Additional functionality for nested arrays?
> - Fallback value for entries that don't have the key? Or perhaps even
> a fallback callback like with array_map()?
> - Option to capture missing entries e.g. in a by-reference variable?
>
> A benefit of keeping the limited functionality would be that
> programming errors are revealed more easily due to the strict
> signature.
>
> A question is how we would look at this long term:
> Do we want both functions to co-exist long-term, or do we want to
> deprecate one of them at some point?
> If array_column() is going to stay, then array_column_assoc() only
> needs to cover the few use cases that are missing.
>
> -- Andreas

If we want to support nested array structures, it could work like this:

NOTE: We actually don't need to squeeze this into array_column_assoc().
We could easily introduce a 3rd function instead, e.g.
array_column_recursive(), if/when we want to have this in the future.
I am only posting this so that we get an idea about the surrounding
design space.

$source['a']['b']['x']['c']['y'] = 5;
$expected['a']['b']['c'] = 5;
assert($expected === array_column_assoc($source, [null, null, 'x', null, 'y']));

Note the first NULL, which only exists to make the system feel more "complete".
This could be useful if the array is coming from a function call.
The following examples show this:

unset($source, $expected);  // (reset vars)
$source['a']['x']['b'] = 5;
$expected['a']['b'] = 5;
assert($expected === array_column_assoc($source, [null, 'x']));
assert($expected === array_column_assoc($source, 'x'));

unset($source, $expected);  // (reset vars)
$source['x']['a'] = 5;
$expected['a'] = 5;
assert($expected === array_column_assoc($source, ['x']));
assert($expected === $source['x'] ?? []);

Trailing NULLs do almost nothing, except to ensure that non-arrays are
removed from the tree.
I would have to think more about the details, but I think it would
work like this:

unset($source, $expected);  // (reset vars)
$source['a0']['b'] = 5;
$source['a1'] = 5;
$expected = $actual;
assert($expected === array_column_assoc($source, []));
assert($expected === array_column_assoc($source, [null]));
unset($expected['a1']);
assert($expected === array_column_assoc($source, [null, null]));
unset($expected['a0']);
assert($expected === array_column_assoc($source, [null, null]));

Another idea could be to "collapse" array levels, using a magic value
other than NULL, that does not work as an array key.

unset($source, $expected);  // (reset vars)
$source['a0']['b0'] = 5;
$source['a1']['b1'] = 5;
$expected['b0'] = 5;
$expected['b1'] = 5;
assert($expected === array_column_assoc($source, [false]));
unset($expected);
$expected['a0'] = 5;
$expected['a1'] = 5;
assert($expected === array_column_assoc($source, [null, false]));

-- Andreas

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to