2015-12-20 -> 2020-08-04
This class contains functions for manipulating arrays.
Note: some examples use the a function, which comes from the bigbang technique. If you don't use bigbang, you can use var_dump as a replacement.
- arrayKeyExistAll
- arrayMergeReplaceRecursive
- arrayUniqueRecursive
- arrayWalkKeys
- arrayWalkKeysRecursive
- filterByAllowed
- filterRecursive
- getMissingKeys
- hasSameValues
- insertRowAfter
- isIdentical
- isNumericalArray
- keysSameAsValues
- mirrorRange
- objectToArray
- reduce
- removeEntry
- splice
- superimpose
- updateNodeRecursive
- walkRowsRecursive
2018-01-18 -> 2020-06-29
bool arrayKeyExistAll ( mixed:keys, array:pool, bool throwEx=false, array &missingKeys = [])
Checks that every given keys exist in the given pool array, and returns the result as a boolean.
If the throwEx flag is set to true, then this method throws an exception as soon as a missing key is found. If it's set to false, the missing keys are available via the missingKeys array.
<?php
$keys = ['a', 'b', 'c'];
$pool = ['a', 'd'];
a(ArrayTool::arrayKeyExistAll($keys, $pool)); // false
a(ArrayTool::arrayKeyExistAll($keys, $pool, true)); // throws an exception
2019-01-17
array arrayMergeReplaceRecursive ( array:arrays)
Merge the given arrays and return a resulting array, appending numeric keys, and replacing existing associative keys.
The merging rules are basically the following:
- set the associative key only if it doesn't already exist
- if it's a numeric key, append it
Given array1:
array(1) {
["example"] => array(2) {
["fruits"] => array(2) {
[0] => string(5) "apple"
[1] => string(6) "banana"
}
["numbers"] => array(2) {
["one"] => int(1)
["two"] => int(2)
}
}
}
and array2:
array(1) {
["example"] => array(3) {
["fruits"] => array(1) {
[0] => string(6) "cherry"
}
["sports"] => array(2) {
[0] => string(4) "judo"
[1] => string(6) "karate"
}
["numbers"] => array(1) {
["two"] => int(222)
}
}
}
The result of Bat::arrayMergeReplaceRecursive([array1, array2]) gives:
array(1) {
["example"] => array(3) {
["fruits"] => array(3) {
[0] => string(5) "apple"
[1] => string(6) "banana"
[2] => string(6) "cherry"
}
["numbers"] => array(2) {
["one"] => int(1)
["two"] => int(222)
}
["sports"] => array(2) {
[0] => string(4) "judo"
[1] => string(6) "karate"
}
}
}
2017-05-04
array arrayUniqueRecursive ( array:arr)
Returns an array after applying the "unique" filter recursively to it.
<?php
$input = array_merge_recursive($profile1, $profile2);
$input = Bat::arrayUniqueRecursive($input);
2020-06-29
array arrayWalkKeys ( array:&arr, callable:fn)
Walks the given array, applying the given callable to every key.
The callable must return a valid key (i.e. a string or a number).
The following,
<?php
$tags = [
'fruit' => 'apple',
'color' => 'red',
];
ArrayTool::arrayWalkKeys($tags, function ($k) {
return '{' . $k . '}';
});
az($tags);
will output something like this:
array(2) {
["{fruit}"] => string(5) "apple"
["{color}"] => string(3) "red"
}
2020-07-02
array arrayWalkKeysRecursive ( array:&arr, callable:fn)
Walks the given array recursively, applying the given callable to every key.
The callable must return a valid key (i.e. a string or a number).
The following,
<?php
$a = [
"fruits" => [
"apple" => 64,
"banana" => 65,
],
];
ArrayTool::arrayWalkKeysRecursive($a, function($k){
if('apple' === $k){
$k = "pomme";
}
return $k;
});
az($a);
will output something like this:
array(1) {
["fruits"] => array(2) {
["banana"] => int(65)
["pomme"] => int(64)
}
}
2019-08-07
array filterByAllowed ( array:arr, array:allowed)
Returns the "arr" array, without the entries which keys are NOT listed in "allowed".
$array = [
"one" => 11,
"two" => 22,
"garbage" => 123,
];
$allowed = ["one", "two"];
az(ArrayTool::filterByAllowed($array, $allowed));
This will output:
array(2) {
["one"] => int(11)
["two"] => int(22)
}
2019-08-09
array filterByAllowed ( array:arr, callable:callback)
Filters the elements of an array recursively, using a given callable.
The callable function must return a boolean (whether to accept the value or remove it).
$arr = [
[
"id" => "one",
"children" => [],
],
[
"id" => "two",
"children" => [
[
"id" => "three",
"children" => [],
],
],
],
];
$a = ArrayTool::filterRecursive($arr, function () {
return true;
});
$b = ArrayTool::filterRecursive($arr, function () {
return false;
});
$c = ArrayTool::filterRecursive($arr, function ($value) {
if (
is_array($value) &&
array_key_exists("id", $value) &&
"three" === $value["id"]
) {
return false;
}
return true;
});
a($a, $b, $c);
This will output:
array(2) {
[0] => array(2) {
["id"] => string(3) "one"
["children"] => array(0) {
}
}
[1] => array(2) {
["id"] => string(3) "two"
["children"] => array(1) {
[0] => array(2) {
["id"] => string(5) "three"
["children"] => array(0) {
}
}
}
}
}
array(0) {
}
array(2) {
[0] => array(2) {
["id"] => string(3) "one"
["children"] => array(0) {
}
}
[1] => array(2) {
["id"] => string(3) "two"
["children"] => array(0) {
}
}
}
2015-12-20
array|false getMissingKeys ( array:arr, array:keys )
Check that all given $keys exist (as keys) in the given $arr. If not, returns the missing keys.
<?php
use Ling\Bat\ArrayTool;
require_once "bigbang.php";
$arr = [
"firstName" => 'peter',
"lastName" => 'Parker',
"job" => 'spiderman',
];
a(ArrayTool::getMissingKeys($arr, ['firstName', 'powers', 'girlFriend'])); // [powers, girlFriend]
a(ArrayTool::getMissingKeys($arr, ['firstName', 'lastName'])); // false
2020-06-11
bool hasSameValues ( array:a, array:b)
Returns whether array a and b contains the same values; The order doesn't matter.
<?php
$a = ["a", "b"];
$b = ["b", "a"];
az(ArrayTool::hasSameValues($a, $b)); // true
2018-04-30
void insertRowAfter ( int:index, array:row, array:&rows )
Insert the given row into the rows.
<?php
$arr = [
[
"name" => "peter",
"age" => "46",
],
[
"name" => "andrea",
"age" => "28",
],
[
"name" => "fabrizzio",
"age" => "13",
],
];
ArrayTool::insertRowAfter(1, [
"name" => "mélanie",
"age" => "5",
], $arr);
a($arr); // melanie is now after andrea...
2019-11-04
array intersect ( array:array, array:keys )
Returns an array containing all the key/value pairs of the given $array which keys are in the given $keys.
The following code:
<?php
$userCols = [
"id" => 6,
"pseudo" => "morris",
"fake" => 789,
];
$realCols = ["id", "pseudo"];
az(ArrayTool::intersect($userCols, $realCols));
will produce this output:
array(2) {
["id"] => int(6)
["pseudo"] => string(6) "morris"
}
The following code:
$userCols = [
"kan" => 6,
];
$realCols = ["id", "pseudo"];
az(ArrayTool::intersect($userCols, $realCols));
will produce this output:
array(0) {
}
2020-06-11
bool isIdentical ( array:a, array:b )
Returns whether array a and b are identical. The order of keys matters.
<?php
$a = ['a' => [1, 2]];
$b = ['a' => [1, 3]];
az(ArrayTool::isIdentical($a, $b)); // false
2019-07-17
void isNumericalArray ( mixed:array, bool:emptyIsValid=true )
Returns whether the given argument is an array which first key is numerical.
Note: supposedly if the first key is numerical, chances are that the whole array is numerical, depending on the array structure. This method was designed to give a quick guess, as opposed to check all the keys of the array, which might take too long depending on the array size.
<?php
$arr = ["a", "b" , "c"];
a(ArrayTool::isNumericalArray($arr)); // true
$arr = ["pou" => "a", "b" , "c"];
a(ArrayTool::isNumericalArray($arr));
2018-03-25
array keysSameAsValues ( array:values )
Return an array with keys equal to values.
<?php
$values = ["blue", "red"];
a(ArrayTool::keysSameAsValues($values));
?>
<pre>
array(2) {
["blue"] => string(4) "blue"
["red"] => string(3) "red"
}
</pre>
2017-10-30
array mirrorRange ( mixed:start, mixed:end, mixed:step = 1 )
Like php range function, but the ranges applies on both the values and the keys (i.e. not just the values like the php range function does).
<?php
az(ArrayTool::mirrorRange(1,10));
/**
* Displays this:
*
* array(10) {
* [1] => int(1)
* [2] => int(2)
* [3] => int(3)
* [4] => int(4)
* [5] => int(5)
* [6] => int(6)
* [7] => int(7)
* [8] => int(8)
* [9] => int(9)
* [10] => int(10)
* }
*/
2019-07-13 -> 2019-12-20
array objectToArray ( obj object, bool deep = true )
This method returns the array corresponding to an object, including non public members.
If the deep flag is true, is will operate recursively, otherwise (if false) just at the first level.
This example (using the service container from the light framework):
<?php
$user = $service->get("user_manager")->getUser();
a($user);
$user = ArrayTool::objectToArray($user);
a($user);
displays the following output:
object(Ling\Light_User\LightWebsiteUser)#157 (7) {
["email":"Ling\Light_User\LightWebsiteUser":private] => string(19) "lingtalfi@gmail.com"
["avatar_url":protected] => string(58) "/plugins/Light_Kit_Admin/zeroadmin/img/avatars/photo-1.jpg"
["pseudo":protected] => string(4) "Ling"
["connect_time":protected] => int(1562970049)
["last_refresh_time":protected] => int(1562970049)
["session_duration":protected] => int(500)
["rights":protected] => array(0) {
}
}
array(7) {
["email"] => string(19) "lingtalfi@gmail.com"
["avatar_url"] => string(58) "/plugins/Light_Kit_Admin/zeroadmin/img/avatars/photo-1.jpg"
["pseudo"] => string(4) "Ling"
["connect_time"] => int(1562970049)
["last_refresh_time"] => int(1562970049)
["session_duration"] => int(500)
["rights"] => array(0) {
}
}
2019-09-17
array reduce ( array:rows, string:column)
Returns a one dimensional numerically indexed array, which values are the row[column] values.
The following code:
<?php
$rows = [
[
"id" => 1,
"name" => "paul",
],
[
"id" => 2,
"name" => "mike",
],
];
az(ArrayTool::reduce($rows, "name"));
Will produce this output:
array(2) {
[0] => string(4) "paul"
[1] => string(4) "mike"
}
2019-11-05
array replaceRecursive ( array tags, array &arr )
Parses the given array recursively replacing the tag keys by their values directly in the array values of type string, using str_replace under the hood.
Tags is an array of key/value pairs, such as:
- {myTag} => 123
- {myTag2} => abc
Only scalar values are accepted. If you need to replace with non scalar values such as arrays, you might be interested in the [ArrayVariableResolver]https://github.com/lingtalfi/ArrayVariableResolver tool.
The following code:
<?php
$arr = [
'key1' => 'value 1',
'key2' => '{computer} and {computer} and {fruit}',
];
$tags = [
'{computer}' => 'mac',
'{fruit}' => 'apple',
];
ArrayTool::replaceRecursive($tags, $arr);
az($arr);
Will produce the following output:
array(2) {
["key1"] => string(7) "value 1"
["key2"] => string(21) "mac and mac and apple"
}
2018-02-16
void removeEntry ( mixed:entry, array:&$arr)
remove the entry from the array.
<?php
$arr = ["red", "blue", "green"];
ArrayTool::removeEntry("blue", $arr);
a($arr);
/**
* Displays this:
*
* array(2) {
* [0] => string(3) "red"
* [2] => string(5) "green"
* }
*/
2020-08-04
void splice (&$input, $offset, $length, $replacement = array())
Same as php array_splice, but preserve keys.
<?php
$p = [
"one" => 111,
"two" => 222,
"three" => 333,
];
ArrayTool::splice($p,1,1, [
"five" => 555,
"four" => 444,
]);
az($p);
Will output something like:
array(4) {
["one"] => int(111)
["five"] => int(555)
["four"] => int(444)
["three"] => int(333)
}
2017-06-08
array superimpose(array layer, array base)
Put the layer array on top of the base array, and return an array containing only the base keys, which values are replaced by the layer values if available.
<?php
$replace = [
"aoo" => 6,
"doo" => 67,
"coo" => 68,
];
$base = [
"aoo" => 78,
"boo" => 78,
];
$result = ArrayTool::superimpose($replace, $base);
a($result);
/**
* Returns the following
*
* array(2) {
* ["aoo"] => int(6)
* ["boo"] => int(78)
* }
*/
2018-05-29
array updateNodeRecursive (array &$arr, callable $callback, array $options = [])
Updates an array recursively, like (php) array_walk_recursive, but adapted for nested item structures.
A nested item structure looks like this for instance:
- id: one label: One children: []
- id: two label: Two children: - id: three label: Three children: []
Children nodes must be referenced directly in the nodes using the "children" key by default.
Options:
- childrenKey: string=children, the name of the key used to reference the children of a node
<?php
$linkFmt = A::link("Ekom_category", [
"type" => '{type}',
"slug" => '{slug}',
]);
ArrayTool::updateNodeRecursive($ret, function (array &$row) use ($linkFmt) {
$row['link'] = str_replace([
"{type}",
"{slug}",
], [
$row['type'],
$row['slug'],
], $linkFmt);
});
2019-09-06
void walkRowsRecursive (array $arr, callable $callback, $childrenKey=children, bool $triggerCallableOnParents = true )
Walks the given rows recursively, triggering the given callback on each row.
A row is an array. Generally all rows have the same structure. A row can contain other rows, in which case it's a parent row. The parent row holds its children using a children key, which defaults to children (third argument).
The callable receives the row as its only argument.
By default, the callable is called for every row, including the parent rows. If you want to trigger the callable only on leaves (rows with no children), you can set the $triggerCallableOnParents flag to false.
The following code:
<?php
$groups = [
[
'action_id' => 'Light_Realist-delete_rows',
'text' => 'Delete',
'icon' => 'far fa-trash-alt'
],
[
'text' => 'Share',
'icon' => 'fas fa-share-square',
'items' => [
[
'action_id' => 'Light_Realist-rows_to_csv',
'icon' => 'far fa-envelope',
'text' => 'Csv',
],
],
],
];
$all = [];
ArrayTool::walkRowsRecursive($groups, function (array $item) use (&$all) {
$all[] = $item;
}, 'items');
az($all);
Will output:
array(3) {
[0] => array(3) {
["action_id"] => string(25) "Light_Realist-delete_rows"
["text"] => string(6) "Delete"
["icon"] => string(16) "far fa-trash-alt"
}
[1] => array(3) {
["text"] => string(5) "Share"
["icon"] => string(19) "fas fa-share-square"
["items"] => array(1) {
[0] => array(3) {
["action_id"] => string(25) "Light_Realist-rows_to_csv"
["icon"] => string(15) "far fa-envelope"
["text"] => string(3) "Csv"
}
}
}
[2] => array(3) {
["action_id"] => string(25) "Light_Realist-rows_to_csv"
["icon"] => string(15) "far fa-envelope"
["text"] => string(3) "Csv"
}
}
The following code:
$groups = [
[
'action_id' => 'Light_Realist-delete_rows',
'text' => 'Delete',
'icon' => 'far fa-trash-alt'
],
[
'text' => 'Share',
'icon' => 'fas fa-share-square',
'items' => [
[
'action_id' => 'Light_Realist-rows_to_csv',
'icon' => 'far fa-envelope',
'text' => 'Csv',
],
],
],
];
$children = [];
ArrayTool::walkRowsRecursive($groups, function (array $item) use (&$children) {
$children[] = $item;
}, 'items', false);
az($children);
Will output:
array(2) {
[0] => array(3) {
["action_id"] => string(25) "Light_Realist-delete_rows"
["text"] => string(6) "Delete"
["icon"] => string(16) "far fa-trash-alt"
}
[1] => array(3) {
["action_id"] => string(25) "Light_Realist-rows_to_csv"
["icon"] => string(15) "far fa-envelope"
["text"] => string(3) "Csv"
}
}
The following code:
$groups = [
[
'action_id' => 'Light_Realist-delete_rows',
'text' => 'Delete',
'icon' => 'far fa-trash-alt'
],
[
'text' => 'Share',
'icon' => 'fas fa-share-square',
'items' => [
[
'action_id' => 'Light_Realist-rows_to_csv',
'icon' => 'far fa-envelope',
'text' => 'Csv',
],
],
],
];
ArrayTool::walkRowsRecursive($groups, function (array &$item) {
$item['mushroom'] = "ok";
}, 'items', false);
az($groups);
Will output:
array(2) {
[0] => array(4) {
["action_id"] => string(25) "Light_Realist-delete_rows"
["text"] => string(6) "Delete"
["icon"] => string(16) "far fa-trash-alt"
["mushroom"] => string(2) "ok"
}
[1] => array(3) {
["text"] => string(5) "Share"
["icon"] => string(19) "fas fa-share-square"
["items"] => array(1) {
[0] => array(4) {
["action_id"] => string(25) "Light_Realist-rows_to_csv"
["icon"] => string(15) "far fa-envelope"
["text"] => string(3) "Csv"
["mushroom"] => string(2) "ok"
}
}
}
}