mirror of
https://github.com/php/php-src.git
synced 2024-12-25 09:49:08 +08:00
array_column: Implement ability to specify an index column
This commit is contained in:
parent
94d5b2519a
commit
5bc2854b37
@ -2563,42 +2563,66 @@ PHP_FUNCTION(array_count_values)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array array_column(array input, mixed key)
|
||||
Return the values from a single column in the input array, identified by the key */
|
||||
/* {{{ proto array array_column(array input, mixed column_key[, mixed index_key])
|
||||
Return the values from a single column in the input array, identified by the
|
||||
value_key and optionally indexed by the index_key */
|
||||
PHP_FUNCTION(array_column)
|
||||
{
|
||||
zval *zarray, *zoffset, **data, **zvalue;
|
||||
zval *zarray, *zcolumn, *zkey = NULL, **data, **zcolval, **zkeyval;
|
||||
HashTable *arr_hash;
|
||||
HashPosition pointer;
|
||||
long index = 0;
|
||||
char *key = NULL;
|
||||
int key_len = 0;
|
||||
ulong column_idx = 0, key_idx = 0, keyval_idx = 0;
|
||||
char *column = NULL, *key = NULL, *keyval = NULL;
|
||||
int column_len = 0, key_len = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az", &zarray, &zoffset) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az|z", &zarray, &zcolumn, &zkey) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Z_TYPE_P(zoffset)) {
|
||||
switch (Z_TYPE_P(zcolumn)) {
|
||||
case IS_NULL:
|
||||
index = 0;
|
||||
column_idx = 0;
|
||||
break;
|
||||
case IS_LONG:
|
||||
index = Z_LVAL_P(zoffset);
|
||||
column_idx = Z_LVAL_P(zcolumn);
|
||||
break;
|
||||
case IS_STRING:
|
||||
key = Z_STRVAL_P(zoffset);
|
||||
key_len = Z_STRLEN_P(zoffset);
|
||||
column = Z_STRVAL_P(zcolumn);
|
||||
column_len = Z_STRLEN_P(zcolumn);
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
convert_to_string(zoffset);
|
||||
key = Z_STRVAL_P(zoffset);
|
||||
key_len = Z_STRLEN_P(zoffset);
|
||||
convert_to_string(zcolumn);
|
||||
column = Z_STRVAL_P(zcolumn);
|
||||
column_len = Z_STRLEN_P(zcolumn);
|
||||
break;
|
||||
default:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The key should be either a string or an integer");
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The column key should be either a string or an integer");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (zkey) {
|
||||
switch (Z_TYPE_P(zkey)) {
|
||||
case IS_NULL:
|
||||
key_idx = 0;
|
||||
break;
|
||||
case IS_LONG:
|
||||
key_idx = Z_LVAL_P(zkey);
|
||||
break;
|
||||
case IS_STRING:
|
||||
key = Z_STRVAL_P(zkey);
|
||||
key_len = Z_STRLEN_P(zkey);
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
convert_to_string(zkey);
|
||||
key = Z_STRVAL_P(zkey);
|
||||
key_len = Z_STRLEN_P(zkey);
|
||||
break;
|
||||
default:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The index key should be either a string or an integer");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
arr_hash = Z_ARRVAL_P(zarray);
|
||||
array_init(return_value);
|
||||
|
||||
@ -2607,14 +2631,47 @@ PHP_FUNCTION(array_column)
|
||||
zend_hash_move_forward_ex(arr_hash, &pointer)) {
|
||||
|
||||
if (Z_TYPE_PP(data) == IS_ARRAY) {
|
||||
if (key && zend_hash_find(Z_ARRVAL_PP(data), key, key_len + 1, (void**)&zvalue) == FAILURE) {
|
||||
if (column && zend_hash_find(Z_ARRVAL_PP(data), column, column_len + 1, (void**)&zcolval) == FAILURE) {
|
||||
continue;
|
||||
} else if (!key && zend_hash_index_find(Z_ARRVAL_PP(data), index, (void**)&zvalue) == FAILURE) {
|
||||
} else if (!column && zend_hash_index_find(Z_ARRVAL_PP(data), column_idx, (void**)&zcolval) == FAILURE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Z_ADDREF_PP(zvalue);
|
||||
add_next_index_zval(return_value, *zvalue);
|
||||
Z_ADDREF_PP(zcolval);
|
||||
|
||||
keyval = NULL;
|
||||
keyval_idx = NULL;
|
||||
|
||||
if (zkey) {
|
||||
if (key && zend_hash_find(Z_ARRVAL_PP(data), key, key_len + 1, (void**)&zkeyval) == FAILURE) {
|
||||
keyval_idx = NULL;
|
||||
} else if (!key && zend_hash_index_find(Z_ARRVAL_PP(data), key_idx, (void**)&zkeyval) == FAILURE) {
|
||||
keyval_idx = NULL;
|
||||
} else {
|
||||
switch (Z_TYPE_PP(zkeyval)) {
|
||||
case IS_LONG:
|
||||
keyval_idx = Z_LVAL_PP(zkeyval);
|
||||
break;
|
||||
case IS_STRING:
|
||||
keyval = Z_STRVAL_PP(zkeyval);
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
convert_to_string(*zkeyval);
|
||||
keyval = Z_STRVAL_PP(zkeyval);
|
||||
break;
|
||||
default:
|
||||
keyval_idx = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (keyval) {
|
||||
add_assoc_zval(return_value, keyval, *zcolval);
|
||||
} else if (keyval_idx != NULL) {
|
||||
add_index_zval(return_value, keyval_idx, *zcolval);
|
||||
} else {
|
||||
add_next_index_zval(return_value, *zcolval);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -435,7 +435,8 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_array_column, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */
|
||||
ZEND_ARG_INFO(0, key)
|
||||
ZEND_ARG_INFO(0, column_key)
|
||||
ZEND_ARG_INFO(0, index_key)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_array_reverse, 0, 0, 1)
|
||||
|
@ -3,7 +3,7 @@ Test array_column() function: basic functionality
|
||||
--FILE--
|
||||
<?php
|
||||
/* Prototype:
|
||||
* array array_column(array $input, mixed $key);
|
||||
* array array_column(array $input, mixed $column_key[, mixed $index_key]);
|
||||
* Description:
|
||||
* Returns an array containing all the values from
|
||||
* the specified "column" in a two-dimensional array.
|
||||
@ -35,6 +35,12 @@ var_dump(array_column($records, 'first_name'));
|
||||
echo "-- id column from recordset --\n";
|
||||
var_dump(array_column($records, 'id'));
|
||||
|
||||
echo "-- last_name column from recordset, keyed by value from id column --\n";
|
||||
var_dump(array_column($records, 'last_name', 'id'));
|
||||
|
||||
echo "-- last_name column from recordset, keyed by value from first_name column --\n";
|
||||
var_dump(array_column($records, 'last_name', 'first_name'));
|
||||
|
||||
echo "\n*** Testing multiple data types ***\n";
|
||||
$file = basename(__FILE__);
|
||||
$fh = fopen($file, 'r', true);
|
||||
@ -73,6 +79,7 @@ $values = array(
|
||||
)
|
||||
);
|
||||
var_dump(array_column($values, 'value'));
|
||||
var_dump(array_column($values, 'value', 'id'));
|
||||
|
||||
echo "\n*** Testing numeric column keys ***\n";
|
||||
$numericCols = array(
|
||||
@ -81,10 +88,12 @@ $numericCols = array(
|
||||
array('ccc', '333')
|
||||
);
|
||||
var_dump(array_column($numericCols, 1));
|
||||
var_dump(array_column($numericCols, 1, 0));
|
||||
|
||||
echo "\n*** Testing failure to find specified column ***\n";
|
||||
var_dump(array_column($numericCols, 2));
|
||||
var_dump(array_column($numericCols, 'foo'));
|
||||
var_dump(array_column($numericCols, 0, 'foo'));
|
||||
|
||||
echo "\n*** Testing single dimensional array ***\n";
|
||||
$singleDimension = array('foo', 'bar', 'baz');
|
||||
@ -92,10 +101,16 @@ var_dump(array_column($singleDimension, 1));
|
||||
|
||||
echo "\n*** Testing columns not present in all rows ***\n";
|
||||
$mismatchedColumns = array(
|
||||
array('a' => 'foo', 'b' => 'bar'),
|
||||
array('a' => 'baz', 'c' => 'qux'),
|
||||
array('a' => 'foo', 'b' => 'bar', 'e' => 'bbb'),
|
||||
array('a' => 'baz', 'c' => 'qux', 'd' => 'aaa'),
|
||||
array('a' => 'eee', 'b' => 'fff', 'e' => 'ggg'),
|
||||
);
|
||||
var_dump(array_column($mismatchedColumns, 'c'));
|
||||
var_dump(array_column($mismatchedColumns, 'c', 'a'));
|
||||
var_dump(array_column($mismatchedColumns, 'a', 'd'));
|
||||
var_dump(array_column($mismatchedColumns, 'a', 'e'));
|
||||
var_dump(array_column($mismatchedColumns, 'b'));
|
||||
var_dump(array_column($mismatchedColumns, 'b', 'a'));
|
||||
|
||||
echo "\n*** Testing use of object converted to string ***\n";
|
||||
class Foo
|
||||
@ -105,8 +120,17 @@ class Foo
|
||||
return 'last_name';
|
||||
}
|
||||
}
|
||||
class Bar
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
return 'first_name';
|
||||
}
|
||||
}
|
||||
$f = new Foo();
|
||||
$b = new Bar();
|
||||
var_dump(array_column($records, $f));
|
||||
var_dump(array_column($records, $f, $b));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
@ -130,6 +154,24 @@ array(3) {
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
-- last_name column from recordset, keyed by value from id column --
|
||||
array(3) {
|
||||
[1]=>
|
||||
string(3) "Doe"
|
||||
[2]=>
|
||||
string(5) "Smith"
|
||||
[3]=>
|
||||
string(5) "Jones"
|
||||
}
|
||||
-- last_name column from recordset, keyed by value from first_name column --
|
||||
array(3) {
|
||||
["John"]=>
|
||||
string(3) "Doe"
|
||||
["Sally"]=>
|
||||
string(5) "Smith"
|
||||
["Jane"]=>
|
||||
string(5) "Jones"
|
||||
}
|
||||
|
||||
*** Testing multiple data types ***
|
||||
array(8) {
|
||||
@ -151,6 +193,25 @@ array(8) {
|
||||
[7]=>
|
||||
resource(5) of type (stream)
|
||||
}
|
||||
array(8) {
|
||||
[1]=>
|
||||
object(stdClass)#1 (0) {
|
||||
}
|
||||
[2]=>
|
||||
float(34.2345)
|
||||
[3]=>
|
||||
bool(true)
|
||||
[4]=>
|
||||
bool(false)
|
||||
[5]=>
|
||||
NULL
|
||||
[6]=>
|
||||
int(1234)
|
||||
[7]=>
|
||||
string(3) "Foo"
|
||||
[8]=>
|
||||
resource(5) of type (stream)
|
||||
}
|
||||
|
||||
*** Testing numeric column keys ***
|
||||
array(3) {
|
||||
@ -161,12 +222,28 @@ array(3) {
|
||||
[2]=>
|
||||
string(3) "333"
|
||||
}
|
||||
array(3) {
|
||||
["aaa"]=>
|
||||
string(3) "111"
|
||||
["bbb"]=>
|
||||
string(3) "222"
|
||||
["ccc"]=>
|
||||
string(3) "333"
|
||||
}
|
||||
|
||||
*** Testing failure to find specified column ***
|
||||
array(0) {
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(3) "aaa"
|
||||
[1]=>
|
||||
string(3) "bbb"
|
||||
[2]=>
|
||||
string(3) "ccc"
|
||||
}
|
||||
|
||||
*** Testing single dimensional array ***
|
||||
array(0) {
|
||||
@ -177,6 +254,38 @@ array(1) {
|
||||
[0]=>
|
||||
string(3) "qux"
|
||||
}
|
||||
array(1) {
|
||||
["baz"]=>
|
||||
string(3) "qux"
|
||||
}
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(3) "foo"
|
||||
["aaa"]=>
|
||||
string(3) "baz"
|
||||
[1]=>
|
||||
string(3) "eee"
|
||||
}
|
||||
array(3) {
|
||||
["bbb"]=>
|
||||
string(3) "foo"
|
||||
[0]=>
|
||||
string(3) "baz"
|
||||
["ggg"]=>
|
||||
string(3) "eee"
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(3) "bar"
|
||||
[1]=>
|
||||
string(3) "fff"
|
||||
}
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
string(3) "bar"
|
||||
["eee"]=>
|
||||
string(3) "fff"
|
||||
}
|
||||
|
||||
*** Testing use of object converted to string ***
|
||||
array(3) {
|
||||
@ -187,4 +296,12 @@ array(3) {
|
||||
[2]=>
|
||||
string(5) "Jones"
|
||||
}
|
||||
array(3) {
|
||||
["John"]=>
|
||||
string(3) "Doe"
|
||||
["Sally"]=>
|
||||
string(5) "Smith"
|
||||
["Jane"]=>
|
||||
string(5) "Jones"
|
||||
}
|
||||
Done
|
||||
|
@ -3,7 +3,7 @@ Test array_column() function: error conditions
|
||||
--FILE--
|
||||
<?php
|
||||
/* Prototype:
|
||||
* array array_column(array $input, mixed $key);
|
||||
* array array_column(array $input, mixed $column_key[, mixed $index_key]);
|
||||
* Description:
|
||||
* Returns an array containing all the values from
|
||||
* the specified "column" in a two-dimensional array.
|
||||
@ -17,24 +17,30 @@ var_dump(array_column());
|
||||
echo "\n-- Testing array_column() function with One argument --\n";
|
||||
var_dump(array_column(array()));
|
||||
|
||||
echo "\n-- Testing array_column() function with more than expected no. of arguments --\n";
|
||||
var_dump(array_column(array(), 'foo', 'bar'));
|
||||
|
||||
echo "\n-- Testing array_column() function with string as first parameter --\n";
|
||||
var_dump(array_column('foo', 0));
|
||||
|
||||
echo "\n-- Testing array_column() function with int as first parameter --\n";
|
||||
var_dump(array_column(1, 'foo'));
|
||||
|
||||
echo "\n-- Testing array_column() key parameter should be a string or an integer (testing bool) --\n";
|
||||
echo "\n-- Testing array_column() column key parameter should be a string or an integer (testing bool) --\n";
|
||||
var_dump(array_column(array(), true));
|
||||
|
||||
echo "\n-- Testing array_column() key parameter should be a string or integer (testing float) --\n";
|
||||
echo "\n-- Testing array_column() column key parameter should be a string or integer (testing float) --\n";
|
||||
var_dump(array_column(array(), 2.3));
|
||||
|
||||
echo "\n-- Testing array_column() key parameter should be a string or integer (testing array) --\n";
|
||||
echo "\n-- Testing array_column() column key parameter should be a string or integer (testing array) --\n";
|
||||
var_dump(array_column(array(), array()));
|
||||
|
||||
echo "\n-- Testing array_column() index key parameter should be a string or an integer (testing bool) --\n";
|
||||
var_dump(array_column(array(), 'foo', true));
|
||||
|
||||
echo "\n-- Testing array_column() index key parameter should be a string or integer (testing float) --\n";
|
||||
var_dump(array_column(array(), 'foo', 2.3));
|
||||
|
||||
echo "\n-- Testing array_column() index key parameter should be a string or integer (testing array) --\n";
|
||||
var_dump(array_column(array(), 'foo', array()));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
@ -42,17 +48,12 @@ echo "Done\n";
|
||||
|
||||
-- Testing array_column() function with Zero arguments --
|
||||
|
||||
Warning: array_column() expects exactly 2 parameters, 0 given in %s on line %d
|
||||
Warning: array_column() expects at least 2 parameters, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
-- Testing array_column() function with One argument --
|
||||
|
||||
Warning: array_column() expects exactly 2 parameters, 1 given in %s on line %d
|
||||
NULL
|
||||
|
||||
-- Testing array_column() function with more than expected no. of arguments --
|
||||
|
||||
Warning: array_column() expects exactly 2 parameters, 3 given in %s on line %d
|
||||
Warning: array_column() expects at least 2 parameters, 1 given in %s on line %d
|
||||
NULL
|
||||
|
||||
-- Testing array_column() function with string as first parameter --
|
||||
@ -65,18 +66,33 @@ NULL
|
||||
Warning: array_column() expects parameter 1 to be array, integer given in %s on line %d
|
||||
NULL
|
||||
|
||||
-- Testing array_column() key parameter should be a string or an integer (testing bool) --
|
||||
-- Testing array_column() column key parameter should be a string or an integer (testing bool) --
|
||||
|
||||
Warning: array_column(): The key should be either a string or an integer in %s on line %d
|
||||
Warning: array_column(): The column key should be either a string or an integer in %s on line %d
|
||||
bool(false)
|
||||
|
||||
-- Testing array_column() key parameter should be a string or integer (testing float) --
|
||||
-- Testing array_column() column key parameter should be a string or integer (testing float) --
|
||||
|
||||
Warning: array_column(): The key should be either a string or an integer in %s on line %d
|
||||
Warning: array_column(): The column key should be either a string or an integer in %s on line %d
|
||||
bool(false)
|
||||
|
||||
-- Testing array_column() key parameter should be a string or integer (testing array) --
|
||||
-- Testing array_column() column key parameter should be a string or integer (testing array) --
|
||||
|
||||
Warning: array_column(): The key should be either a string or an integer in %s on line %d
|
||||
Warning: array_column(): The column key should be either a string or an integer in %s on line %d
|
||||
bool(false)
|
||||
|
||||
-- Testing array_column() index key parameter should be a string or an integer (testing bool) --
|
||||
|
||||
Warning: array_column(): The index key should be either a string or an integer in %s on line %d
|
||||
bool(false)
|
||||
|
||||
-- Testing array_column() index key parameter should be a string or integer (testing float) --
|
||||
|
||||
Warning: array_column(): The index key should be either a string or an integer in %s on line %d
|
||||
bool(false)
|
||||
|
||||
-- Testing array_column() index key parameter should be a string or integer (testing array) --
|
||||
|
||||
Warning: array_column(): The index key should be either a string or an integer in %s on line %d
|
||||
bool(false)
|
||||
Done
|
||||
|
Loading…
Reference in New Issue
Block a user