$source['a0']['b01'] = 5;On Wed, 8 Sept 2021 at 16:48, Andreas Hennings <andr...@dqxtech.net> wrote: > > 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
Another option to support nested arrays, but simpler. Some of the functionality I proposed earlier now needs multiple calls, but I think this is fine. New signature: function array_column_assoc(array $source, string $value_key, int $level = 1); unset($source, $expected, $expected2); // (reset vars) $source['a']['b']['x']['c']['y'] = 5; $expected['a']['b']['c']['y'] = 5; assert($expected === array_column_assoc($source, 'x', 2)); $expected2['a']['b']['c'] = 5; assert($expected2 === array_column_assoc($expected, 'y', 3)); To collapse array levels, we could introduce a separate function. Similar to array_merge(), but preserving all keys. unset($source, $expected); // (reset vars) $source['a0']['b01'] = '0.01'; $source['a0']['b02'] = '0.02'; $source['a1']['b1'] = '1.1'; $expected['b01'] = '0.01; $expected['b02'] = '0.02'; $expected['b1'] = '1.1'; assert($expected === array_collapse($source, 0)); unset($expected); $expected['a0'] = '0.01'; $expected['a1'] = '1.1'; assert($expected === array_collapse($source, 1)); -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php