Table of Contents

Request for Comments: array_part

Introduces a new function array_part() in ext/standard.

Introduction

This RFC proposes a new array function that can extract multidimensional slices for arrays.

Specification for the function

The function array_part() shall have the following signature:

array array_part(array $originalArray, array $partSpecification[, bool $indexesAreKeys = false])

The parameter $originalArray represents the original array from which a part is to be extracted.

The parameter $partSpecification is a sequentially indexed numeric array that specifies the slice to extract at each “level” of the original array. A level n (with n >= 0) of an array $arr is the set of array elements than can be fetched by “dereferencing” the array n times. For instance, the array [[1],[['a','b']]] has at level 0 itself, at level 1 the elements [1] and [['a','b']] and at level 2 the elements 1 and ['a','b']. $partSpecification[0] shall give the part specification for level 1, and, in, general, $partSpecification[m] for level m + 1.

Each part specification shall have one of the following forms:

Span parts extract any number of elements (possibly 0) starting at the index specified by start and advancing until end is reached, advancing in steps of step. The element at the index specified at end is included.

An index i has the following meaning:

The keys in the original array are not preserved in the output, expect at levels that were not visited. References are not preserved when the elements are added to the resulting array.

This function shall return false upon finding error conditions. The following are error conditions:

Proposed implementation

The proposed implementation is available as git branch on github. I'll update the branch it as I improve it. This is not a prototype. If this proposal is accepted, this implementation will be merged.

Sample PHP implementation and usage

A sample implementation, with tests exemplifying the use of this function, is available.

This implementation differs in some respects to the internal implementation with respect to behavior. Its purpose is only to exemplify the usage of the function here proposed.

Direct link to the tests

Comments

I would find this far more useful if the keys were preserved, or at least an option to do so. Or the old standby that INT keys get renumbered but non-INT do not.

Objections

I want native array slicing through a new operator

That's fine, but it is not what this proposal is about. A change to the language presents many more complications which I very much want to avoid -- for instance the current array dereferencing syntax most likely would unusable because -1 represents the element with key -1, not the last element. Besides, the introduction of this function does not prevent native array slicing from being added in the future.

You seem to already have an implementation, why are you pushing this to us?

First, this function would benefit greatly from a native implementation. It's impossible to efficiently detect recursion in userland. The sample makes heavy use of references, which introduces a lot of separations. Traversing arrays without changing the internal pointer is very inefficient in userland.

Of course, the main reason is that this function is useful. Recently, functions like array_column(), array_first() and array_last() have been proposed. This function satisfies all those needs: array_part($arr, [['start'=>null], 'column'], true), array_part($arr, 0) and array_part($arr, -1).

The $indexesAreKeys = false mode is inefficient because there's no constant time access to the n-th element

This is true. We must traverse the array from the start or the end to get to the n-th element. That's just the way PHP arrays are implemented. However, if you have numeric sequential arrays, you can use $indexesAreKeys = true to access the n-th element without this penalty (also note that the sample implementation is not optimized).

Vote

Should the current array_part() implementation be merged
Real name Yes No
aharvey (aharvey)  
ben (ben)  
cataphract (cataphract)  
hradtke (hradtke)  
hytest (hytest)  
ircmaxell (ircmaxell)  
juliens (juliens)  
kinncj (kinncj)  
klaussilveira (klaussilveira)  
levim (levim)  
lstrojny (lstrojny)  
mgf (mgf)  
nikic (nikic)  
olemarkus (olemarkus)  
peehaa (peehaa)  
shm (shm)  
sqmk (sqmk)  
stas (stas)  
willfitch (willfitch)  
Count: 2 17

Changelog