Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:116011 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 30416 invoked from network); 8 Sep 2021 14:29:55 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 8 Sep 2021 14:29:55 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id DC4F4180003 for ; Wed, 8 Sep 2021 08:07:38 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_NONE,SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-pj1-f41.google.com (mail-pj1-f41.google.com [209.85.216.41]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 8 Sep 2021 08:07:38 -0700 (PDT) Received: by mail-pj1-f41.google.com with SMTP id j1so1885161pjv.3 for ; Wed, 08 Sep 2021 08:07:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dqxtech-net.20150623.gappssmtp.com; s=20150623; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=8rbLroFO8+grGLkqRRcULqv1FUGC8D/smE96DX8l7Xo=; b=hvdUNnaXvEnDoAaj/rNaQAS/zTPG+VvuI90w0q34owQoWqe6vNCucVCw2Z6G3v/DFl OG+CbZ8mHepAIYAvkm1kP0DZKePyxE/1TMEHgSNNxNed5OcpldeR90qL8P69SjsHo56a 3jbQHT9mSU8cDBjSEYD4w1G7FBMiXJsSQSEzkkeb3gep2HLilMppwPr8uMX3oBnGVW5u AOx2jK3qwzCMglyr97k0RRC6uVMilc7lpP8HEv4PHRahhEQ87JtiRGm29NAUzVXP1pBN iqLI6YixipC99L14Tygz4pKmrBFKHLLmYkbjyu6XAxB36Zzf1TpgHP7QuX3J1zRh4Mdp z4Pw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=8rbLroFO8+grGLkqRRcULqv1FUGC8D/smE96DX8l7Xo=; b=iG7EBWGpXckIsHwJJHTcNCYR8x1PxiVAiyE1/czkO/Thu+PVOM0DSevQe9cq4PzQi1 NY1zgPCfg/RfF//uo4o1ucVOdyUNFUn/kFhmZQIFRXTVFEsbCVmm+SNmuKEGRGl0poKA NMapHlGVclzx4qERjHd0K8zApXHAlhzcA66OU0JC9uLdeMnSvvTiiNSBe80TlCqBNoKc P86qjBsUVHwoUEmbY2EFSUupMWcLpfPyECgG47g6oubIeOsy+1LCtlt+8XlwgfMUvZDs +XU2fQf2w2OGtwDbLtNya8SKomMrcLzZCq9SOEvM5pMVdqpXOLv1kmTDH9FQ08WfKg/H +zSQ== X-Gm-Message-State: AOAM531Ub9tRVYZy9RzwGcAHbFrySlSt+A+RlHaxbRXgrOXL3qjFi1zO DZN4VcIkqcd8z6iFOJDTMyqgiJ1e3WWNQ0syUkPtPpUYewa4Zg== X-Google-Smtp-Source: ABdhPJzw5locKtWa5bt/pB3p3IS3n8Hmc/jLjekztfcb6ga101P1THywMvbCFHfDC3kRhU2tDq6BiiZ02SeoIrHxuJQ= X-Received: by 2002:a17:902:7e06:b0:139:fb90:6734 with SMTP id b6-20020a1709027e0600b00139fb906734mr3429349plm.9.1631113655917; Wed, 08 Sep 2021 08:07:35 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Wed, 8 Sep 2021 17:07:24 +0200 Message-ID: To: Marco Pivetta Cc: PHP internals Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] Option for array_column() to preserve keys. From: andreas@dqxtech.net (Andreas Hennings) $source['a0']['b01'] =3D 5;On Wed, 8 Sept 2021 at 16:48, Andreas Hennings wrote: > > On Wed, 8 Sept 2021 at 16:10, Andreas Hennings wrot= e: > > > > Thanks for the feedback so far! > > > > On Wed, 8 Sept 2021 at 10:13, Marco Pivetta wrote: > > > > > > Heyo, > > > > > > On Wed, 8 Sep 2021, 02:19 Andreas Hennings, wro= te: > > >> > > >> Hello internals, > > >> > > >> The function array_column() would be much more useful if there was a= n > > >> option to preserve the original array keys. > > >> I can create an RFC, but I think it is better to first discuss the o= ptions. > > > > > > > > > New function, please =F0=9F=99=8F > > > > 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 =3D=3D=3D 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'] =3D 5; > $expected['a']['b']['c'] =3D 5; > assert($expected =3D=3D=3D array_column_assoc($source, [null, null, 'x', = null, 'y'])); > > Note the first NULL, which only exists to make the system feel more "comp= lete". > 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'] =3D 5; > $expected['a']['b'] =3D 5; > assert($expected =3D=3D=3D array_column_assoc($source, [null, 'x'])); > assert($expected =3D=3D=3D array_column_assoc($source, 'x')); > > unset($source, $expected); // (reset vars) > $source['x']['a'] =3D 5; > $expected['a'] =3D 5; > assert($expected =3D=3D=3D array_column_assoc($source, ['x'])); > assert($expected =3D=3D=3D $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'] =3D 5; > $source['a1'] =3D 5; > $expected =3D $actual; > assert($expected =3D=3D=3D array_column_assoc($source, [])); > assert($expected =3D=3D=3D array_column_assoc($source, [null])); > unset($expected['a1']); > assert($expected =3D=3D=3D array_column_assoc($source, [null, null])); > unset($expected['a0']); > assert($expected =3D=3D=3D 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'] =3D 5; > $source['a1']['b1'] =3D 5; > $expected['b0'] =3D 5; > $expected['b1'] =3D 5; > assert($expected =3D=3D=3D array_column_assoc($source, [false])); > unset($expected); > $expected['a0'] =3D 5; > $expected['a1'] =3D 5; > assert($expected =3D=3D=3D 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 = =3D 1); unset($source, $expected, $expected2); // (reset vars) $source['a']['b']['x']['c']['y'] =3D 5; $expected['a']['b']['c']['y'] =3D 5; assert($expected =3D=3D=3D array_column_assoc($source, 'x', 2)); $expected2['a']['b']['c'] =3D 5; assert($expected2 =3D=3D=3D 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'] =3D '0.01'; $source['a0']['b02'] =3D '0.02'; $source['a1']['b1'] =3D '1.1'; $expected['b01'] =3D '0.01; $expected['b02'] =3D '0.02'; $expected['b1'] =3D '1.1'; assert($expected =3D=3D=3D array_collapse($source, 0)); unset($expected); $expected['a0'] =3D '0.01'; $expected['a1'] =3D '1.1'; assert($expected =3D=3D=3D array_collapse($source, 1));