Skip to content

Add array_key_first(), array_key_last(), and array_key_index() #347

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

jbafford
Copy link

Add three new functions:

$key = array_key_first($array [, $value])
$key = array_key_last($array [, $value])
$key = array_key_index($array, $index [, $value])

array_key_first() and array_key_last() respectively return the first and last key in an array, and optionally, the value. array_key_index() returns the key belonging to the zero-based index specified, with the ability to search from the end of the array if a negative index is passed.

These functions do this without mutating the source arrays (so, they do not modify the internal array pointer.)

This allows you to do the equivalent of array_keys($arr)[0] (or foreach($arr as $k => $v) { break; }) with less overhead.

@nikic
Copy link
Member

nikic commented May 17, 2013

This will need an RFC :) See https://wiki.php.net/rfc/howto for more info.

Add three new functions:

$key = array_key_first($array [, &$value])
$key = array_key_last($array [, &$value])
$key = array_key_index($array, $index [, &$value])

array_key_first() and array_key_last() respectively return the first and last key in an array, and optionally, the value. array_key_index() returns the key belonging to the zero-based index specified, with the ability to search from the end of the array if a negative index is passed.

These functions do this without mutating the source arrays (so, they do not modify the internal array pointer.)

This allows you to do the equivalent of array_keys($arr)[0] (or foreach($arr as $k => $v) { break; }) with less overhead.
@jbafford jbafford force-pushed the feature/array_key_index branch from c562e25 to 1162676 Compare December 4, 2015 18:53
@linaori
Copy link

linaori commented Dec 14, 2015

Return the array's first key (and optionally, value), could you provide some examples of this maybe? I'm not sure what this method does, simply a getter or also a setter if the second argument is provided? Note that this is quite inconsistent with other php functions.

@jbafford
Copy link
Author

jbafford commented Jan 1, 2016

@iltar A more full description is in the RFC for this PR, with examples: https://wiki.php.net/rfc/array_key_first_last_index

@mattvb91
Copy link

mattvb91 commented Jan 3, 2016

👍 in general but I think this would be alot less confusing without the optional values for array_key_first and array_key_last

@shadowhand
Copy link

I don't see why this is necessary, considering it can be done with 4 lines of polyfill (not counting declarations): https://gist.github.com/shadowhand/844f5005d51c7f5c75c2

@jbafford
Copy link
Author

jbafford commented Jan 4, 2016

reset() modifies the array, which in your polyfill, forces a copy to be made. For large arrays, this can be slow and consume memory. A significantly more performant (in PHP 7 only) polyfill for array_key_first would be:

function array_key_first(array $arr)
{
     foreach($arr as $k => $v) {
        return $k
    }

    return null;
}

But that is honestly still a pretty kludgy solution, and does not actually help with making array_key_last() performant.

The reason the RFC exists is because there is no way to do this in userspace without writing code that is fast, and does not look weird, and does not modify the source array.

@staabm
Copy link
Contributor

staabm commented Jan 4, 2016

Maybe it would be more helpfull to add functions to get & set the position the internal array pointer is pointing to? those could be more usefull for other scenarios and we dont need to add 2 methods for a certain "edge-case"...?

@jerrygrey
Copy link

@staabm The purpose of these new functions isn't about changing the internal pointer, there are already functions to change the pointer e.g. next(), but no functions like these.

@jbafford 👍 from me. I can see a lot of usage of these new functions.

@staabm
Copy link
Contributor

staabm commented Jan 4, 2016

The purpose of these new functions isn't about changing the internal pointer, there are already functions to change the pointer e.g. next(), but no functions like these.

there isnt. you can only move the pointer forwards/backwards but nothing like "tell me where the pointer atm is" or a "set the internal pointer to position x".

@jerrygrey
Copy link

@staabm There is...

tell me where the pointer atm is

key($array) [http://php.net/manual/en/function.key.php]

set the internal pointer to position x

You can use @shadowhand's polyfill code: [https://gist.github.com/shadowhand/844f5005d51c7f5c75c2]

But you are missing the point, there are no functions that don't touch the pointer currently. In a lot of cases, you don't want the pointer to change, this is where these new functions will get the job done.

@laruence laruence added the RFC label Jan 4, 2016
@staabm
Copy link
Contributor

staabm commented Jan 4, 2016

@jerrygrey as commented in https://gist.github.com/shadowhand/844f5005d51c7f5c75c2 with the current functions you need to copy the array to get the required functionality, which wouldnt be required in case we could read/write the position of the internal pointer.

@jerrygrey
Copy link

@staabm I just had a look and all the functions that changes the internal array pointer has a copy element in them, so it would be unavoidable to have a function that changes the pointer without a copy.

@jbafford
Copy link
Author

jbafford commented Jan 4, 2016

The concept of the internal array pointer is an implementation detail, which I don't think should be further leaked into userspace. In any case, that's completely distinct from the problem this RFC is trying to solve.

@mrclay
Copy link

mrclay commented May 18, 2016

Seems like array_slice should already have (or could be improved to have) the performance characteristics you want, and allows preserving key. (userland implementation)

@krakjoe
Copy link
Member

krakjoe commented Jan 7, 2017

I'm glad to see that this RFC is still alive with recent activity ... please push it forward ;)

Just a quick note:

This RFC requires a super majority: It is the consensus of core maintainers that "language change" means anything that we have to continue to maintain after it is merged.

Please update the RFC accordingly.

@jens1o
Copy link

jens1o commented Jun 2, 2017

What does it mean that is under discussion for more than 3 months, does it mean this idea is dead?

@jbafford
Copy link
Author

jbafford commented Jun 2, 2017

@jens1o It's only dead in the sense I just haven't had the time or inclination to deal with this for the last year. I've got a little bit of free time, though, so I'll see what I can do about pushing it along. The RFC basically needs a complete rewrite based on the feedback from when this was initially proposed last year.

@krakjoe Can you point me to a thread indicating the reasoning for why this is a "language change" and a supermajority is required? All this does is add a few functions to the function list. Larger changes have required less support than that.

@carusogabriel
Copy link
Contributor

@jbafford Do you have plans to update this RFC? Or someone can surpass this PR?

@jbafford
Copy link
Author

@carusogabriel This is still on my to-do list, but frankly, I've been busy, and from past experience, not highly inclined to want to spend the necessary mental effort wrangling php-internals.

Realistically speaking, I'm not going to be able to devote any time to this RFC until September or October. That may not be soon enough for the 7.3 merge window, if 7.3 proceeds as 7.0/7.1/7.2. If someone would like to shepherd this RFC into 7.3 before then and thinks they can get a yes vote, then feel free to contact me and I can discuss my recollection of the previous round of discussion and what next steps should be before bringing it up for discussion again. Otherwise, I've set a reminder, and will take a look at it again when I'm back and try and push it through at that time.

@wol-soft
Copy link

@jbafford I've made a different implementation approach with a smaller functional scope covering the basic requirements by adding the functions array_key_first(array $a) and array_key_last(array $a)

wol-soft@ec2332b

I'd like to propose to use the smaller scope, if possible for 7.3.

@someniatko
Copy link

someniatko commented Jul 24, 2018

Is it ok that array_key_first([ null => 1, 'a' => 'b', /* … */ ]) returns null as well as array_key_first([]) does?

@php-pulls
Copy link

Comment on behalf of cmb at php.net:

Since https://wiki.php.net/rfc/array_key_first_last has been accepted and implemented, I'm closing this PR. If you're still interested in adding array_key_index(), I suggest to write a respective RFC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.