In php, I need a function to return all keys in array of objects. For arrays and objects I need keys like parentkey->key. If the key is again an array, then I need parentkey->key->key1.
My code as below
$array=json_decode('{"client":"4","gateWay":"1","store":"store.shop.com",
"valid":"true","po":34535,"additionalPO":23423,"customerNotes":"",
"orderItems":[{"item":"123","quantity":10,"supplierLotNo":"",
"customsValue":"","customsDescription":"","hsCode":""},
{"item":"345","quantity":50}],
"shippingInfos":[{"address":{"city":"Chennai",
"country":"India","postalCode":"86715","state":"TN",
"streetAddress1":"6971 North Street","streetAddress2":null},
"contact":{"company":null,"email":"info#store.com","firstName":"test",
"lastName":"test","phoneNo":null},"ServiceId":"3","thirdPartyAccountNo":"",
"signatureConfirmation":false,"saturdayDelivery":false}]}',true);
function array_keys_multi(array $array,$headkey,$pkey){
$keys = array();$hkey='';$parentkey='';
foreach ($array as $key => $value) {
//echo $key;
if($headkey!='' && !is_integer($headkey)){
if(!is_integer($key)){
if (is_array($value) || is_object($value)) {
if($pkey!='')
$parentkey=$pkey."->".$key;
else
$parentkey=$key;
foreach($value as $kk=>$val){
foreach($val as $kk1=>$val1){
$keys[]=$parentkey."->".$kk1;
}
}
//$keys[]=$parentkey."->".$key;
}else{
$keys[] = $pkey."->".$key;
$hkey=$headkey."->".$key;
}
}
}
else{
if(!is_integer($key)){
if($pkey!='')
$parentkey=$pkey."->".$key;
else
$parentkey=$key;
if (is_array($value) || is_object($value)) {
if($pkey!='')
$parentkey=$pkey."->".$key;
else
$parentkey=$key;
foreach($value as $kk=>$val){
//print_r($val);echo "==========";
foreach($val as $kk1=>$val1){
$keys[]=$parentkey."->".$kk1;
}
}
$hkey=$key;
}else{
$keys[]=$key;
}
}
}
if (is_array($value) || is_object($value)) {
echo $key."-----".$hkey."<br>";
$keys = array_merge($keys, array_keys_multi($value,$hkey,$key));
}
}
return $keys;
}
$k=array_keys_multi($array,'','');
print_r($k);
I need output as an array with the following key paths (notice no numeric keys are retained):
[
"client",
"gateWay",
"store",
"valid",
"po",
"additionalPO",
"customerNotes",
"orderItems->item",
"orderItems->quantity",
"orderItems->supplierLotNo",
"orderItems->customsValue",
"orderItems->customsDescription",
"orderItems->hsCode",
"shippingInfos->address->city",
"shippingInfos->address->country",
"shippingInfos->address->postalCode",
"shippingInfos->address->state",
"shippingInfos->address->streetAddress1",
"shippingInfos->address->streetAddress2",
"shippingInfos->contact->company",
"shippingInfos->contact->email",
"shippingInfos->contact->firstName",
"shippingInfos->contact->lastName",
"shippingInfos->contact->phoneNo",
"shippingInfos->ServiceId",
"shippingInfos->thirdPartyAccountNo",
"shippingInfos->signatureConfirmation",
"shippingInfos->saturdayDelivery"
]
How can I achieve this?
Starting from this very similar recursive snippet, I changed the key path separator and extended the algorithm to exclude numeric keys and parents with children.
Code: (Demo)
function getUniqueObjectKeyPaths($array, $parentKey = "") {
$keys = [];
foreach ($array as $parentKey => $v) {
if (is_array($v)) {
$nestedKeys = getUniqueObjectKeyPaths($v, $parentKey);
foreach($nestedKeys as $index => $key) {
if (!is_numeric($parentKey) && !is_numeric($key)) {
$nestedKeys[$index] = $parentKey . "->" . $key;
}
}
array_push($keys, ...$nestedKeys);
} elseif (!is_numeric($parentKey)) {
$keys[] = $parentKey;
}
}
return $keys;
}
var_export(getUniqueObjectKeyPaths($array));
Output:
array (
0 => 'client',
1 => 'gateWay',
2 => 'store',
3 => 'valid',
4 => 'po',
5 => 'additionalPO',
6 => 'customerNotes',
7 => 'orderItems->item',
8 => 'orderItems->quantity',
9 => 'orderItems->supplierLotNo',
10 => 'orderItems->customsValue',
11 => 'orderItems->customsDescription',
12 => 'orderItems->hsCode',
13 => 'orderItems->item',
14 => 'orderItems->quantity',
15 => 'shippingInfos->address->city',
16 => 'shippingInfos->address->country',
17 => 'shippingInfos->address->postalCode',
18 => 'shippingInfos->address->state',
19 => 'shippingInfos->address->streetAddress1',
20 => 'shippingInfos->address->streetAddress2',
21 => 'shippingInfos->contact->company',
22 => 'shippingInfos->contact->email',
23 => 'shippingInfos->contact->firstName',
24 => 'shippingInfos->contact->lastName',
25 => 'shippingInfos->contact->phoneNo',
26 => 'shippingInfos->ServiceId',
27 => 'shippingInfos->thirdPartyAccountNo',
28 => 'shippingInfos->signatureConfirmation',
29 => 'shippingInfos->saturdayDelivery',
)
Related
For four days I am trying to figure out how to solve this, as well as googling it, and was no luck
The problem is that I needed to loop through a nested array (for unknown deep) and keep the top-level keys (as a prefix to the last value) as long as I am still going deep, and then start over (the prefix need to reset) once it started a new path.
I want to generate complete addresses from this array.
$arr = [
"buildings" => [
"group1" => [
"b1" => [1,2,3,4],
"b2" => [1,2,3]
],
"group2" => [
"b1" => [1,2]
]
],
"villas" =>[
"group1" => [
"v1" => [1,2],
"v2" => [1]
],
"group2" => [
"v1" => [1],
"v2" => [1]
],
"group3" => [
"v1" => [1]
],
]
];
This is the needed output
buildings/group1/b1/1
buildings/group1/b1/2
buildings/group1/b1/3
buildings/group1/b1/4
buildings/group1/b2/1
buildings/group1/b2/2
buildings/group1/b2/3
buildings/group2/b1/1
buildings/group2/b1/2
villas/group1/v1/1
villas/group1/v1/2
villas/group1/v2/1
villas/group2/v1/1
villas/group2/v2/1
villas/group3/v1/1
I tried this function but also it didn't bring the wanted results
function test($array, $path = ""){
foreach ($array as $key => $value) {
if (is_array($value)){
$path .= $key."/";
test($value, $path);
} else {
echo $path.$value."<br>";
}
}
}
test($arr);
UPDATE
I understood where was my mistake and I wanted to share with you my modification to my method after I fixed it.
function test($array, $path = ""){
foreach ($array as $key => $value) {
if (is_array($value)){
test($value, $path . $key . '/');
} else {
echo $path.$value."<br>";
}
}
}
And thanks to #Kai Steinke he's method is way better than mine, and here is some improvements just to make it look better.
function flatten(array $array, array $flattened = [], string $prefix = ''): array
{
foreach ($array as $key => $value) {
if (is_array($value)) {
$flattened = array_merge( flatten($value, $flattened, $prefix . $key . '/'));
continue;
}
$flattened[] = $prefix . $value;
}
return $flattened;
}
Here you go:
function flatten($arr, $prefix = '') {
$result = [];
foreach ($arr as $key => $value) {
if (is_array($value)) {
$result = array_merge($result, flatten($value, $prefix . $key . '/'));
} else {
$result[] = $prefix . $value;
}
}
return $result;
}
// Usage
print_r(flatten($arr))
Returns an Array:
Array (
[0] => buildings/group1/b1/1
[1] => buildings/group1/b1/2
[2] => buildings/group1/b1/3
[3] => buildings/group1/b1/4
[4] => buildings/group1/b2/1
[5] => buildings/group1/b2/2
[6] => buildings/group1/b2/3
[7] => buildings/group2/b1/1
[8] => buildings/group2/b1/2
[9] => villas/group1/v1/1
[10] => villas/group1/v1/2
[11] => villas/group1/v2/1
[12] => villas/group2/v1/1
[13] => villas/group2/v2/1
[14] => villas/group3/v1/1
)
Build and preserve the path using all encountered keys until arriving at a deep non-array value, then append the value to the string, and push the full path into the result array.
Code: (Demo)
function flatten(array $array, string $path = ''): array
{
$result = [];
foreach ($array as $k => $v) {
array_push(
$result,
...(is_array($v) ? flatten($v, "$path$k/") : ["$path$v"])
);
}
return $result;
}
var_export(flatten($array));
A slightly related answer where a slash-delimited string was built as the hierarchical path to a search value.
I have an array, $arr, which looks like this:
'sdb5' => [
'filters' => [
(int) 11 => [
'find' => [
(int) 0 => (int) 569
],
'exclude' => [
(int) 0 => (int) 89,
(int) 1 => (int) 573
]
],
(int) 86 => [
'find' => [
(int) 0 => (int) 49,
(int) 1 => (int) 522,
(int) 2 => (int) 803
],
'exclude' => [
(int) 0 => (int) 530,
(int) 1 => (int) 802,
(int) 2 => (int) 511
]
]
]
],
I've read Delete element from multidimensional-array based on value but am struggling to understand how to delete a value in an efficient way.
For example, let's say I want to delete the value 522. I'm doing it like this:
$remove = 522; // value to remove
foreach ($arr as $filters) {
foreach ($filters as $filter) {
foreach ($filter as $single_filter) {
foreach ($single_filter as $key => $value) {
if ($value == $remove) {
unset($key);
}
}
}
}
}
I couldn't work out from the above link how to do this because even though it's a multidimensional array, it doesn't have any sub-arrays like mine.
I also don't know how else to rewrite this without repeating foreach to get to the elements of the array I want. Again, I've read Avoid multiple foreach loops but cannot apply this to my array.
I am using PHP 7.x.
foreach() made copy of elements. Then unseting the key is not enough, because you are destroying a local variable.
You could use references & in your foreach() loops and unset like :
foreach ($arr as &$filters) {
foreach ($filters as &$filter) {
foreach ($filter as &$single_filter) {
foreach ($single_filter as $key => $value) {
if ($value == $remove) {
unset($single_filter[$key]);
}
}
}
}
}
Or using keys ($k1, $k2, ...) :
foreach ($arr as $k1 => $filters) {
foreach ($filters as $k2 => $filter) {
foreach ($filter as $k3 => $single_filter) {
foreach ($single_filter as $key => $value) {
if ($value == $remove) {
unset($arr[$k1][$k2][$k3][$key]);
}
}
}
}
}
You could also write a recursive function, so you don't have to use nested foreach:
function deleteRecursive(&$array, &$value) {
foreach($array as $key => &$subArray) {
if(is_array($subArray)) {
deleteRecursive($subArray, $value);
} elseif($subArray == $value) {
unset($array[$key]);
}
}
}
$valueToDelete = 522;
deleteRecursive($array, $valueToDelete);
function recursiveRemoval(&$array, $val)
{
if(is_array($array))
{
foreach($array as $key=>&$arrayElement)
{
if(is_array($arrayElement))
{
recursiveRemoval($arrayElement, $val);
}
else
{
if($arrayElement == $val)
{
unset($array[$key]);
}
}
}
}
}
Call function
recursiveRemoval($array, $value);
I am stuck...
I have this value in my PHP:
$arr['something1']['something2'] = value;
I want to have a func($arr) that returns:
$arr['something1[something2]'] = value;
Here is my current codes for nested 3 arrays:
static function flattenArray(array $notFlat, string $pK) {
$index = 0;
foreach ($notFlat as $k => $v) {
if (is_array($v)) {
foreach ($v as $_k => $_v) {
if (is_array($_v)) {
foreach ($_v as $__k => $__v) {
if (is_array($__v)) {}
else{
unset($notFlat[$k]);
$newArray = array_slice($notFlat, 0, $index, true) +
$notFlat[$k] = [$pK.$k.'['.$_k.']'.'['.$__k.']' => $__v] +
array_slice($notFlat, $index, NULL, true);
$notFlat = $newArray;
}
}
}
}
}
$index ++;
}
return $notFlat;
}
But that is too manual... I think recursive function can work but I am not sure what to return in case iterated value is an array.
EDIT1: Expected Output
$asd = ['asd' => ['jkf' => ['qwe' => 'wer', 'asd' => '123', 'kjk' => 'sdf', '456' => 'zxc']], 'dfg', 'test' => ['ert' => '234'], 'cvf'];
print_r(func($asd));
/*
Array
(
[test[ert]] => 234
[asd[jkf][456]] => zxc
[asd[jkf][kjk]] => sdf
[asd[jkf][asd]] => 123
[asd[jkf][qwe]] => wer
[0] => dfg
[1] => cvf
)
*/
function flattenArray(array $notFlat) {
function _flattenArray(&$arrayRoot, $arrayCurr, $kS) {
foreach ($arrayCurr as $k => $v) {
if (is_array($v)) {
_flattenArray($arrayRoot, $v, $kS.'['.$k.']');
}
else {
$currentKey = (string) $kS.'['.$k.']';
$arrayRoot[$currentKey] = $v;
}
}
}
foreach ($notFlat as $k => $v) {
if (is_array($v)) {
_flattenArray($notFlat, $v, $k);
unset($notFlat[$k]);
}
}
return $notFlat;
}
Code ( https://3v4l.org/5LVii )
$asd = ['asd' => ['jkf' => ['qwe' => 'wer', 'asd' => '123', 'kjk' => 'sdf', '456' => 'zxc']], 'dfg', 'test' => ['ert' => '234'], 'cvf'];
function recurse($array,$key=''){
static $output=[];
foreach($array as $k=>$v){
if(is_array($v)){
recurse($v,$key?$key.'['.$k.']':$k);
}else{
$output[$key?$key.'['.$k.']':$k]=$v;
}
}
return $output;
}
var_export(recurse($asd));
Output:
array (
'asd[jkf][qwe]' => 'wer',
'asd[jkf][asd]' => '123',
'asd[jkf][kjk]' => 'sdf',
'asd[jkf][456]' => 'zxc',
0 => 'dfg',
'test[ert]' => '234',
1 => 'cvf',
)
There isn't much that I can explain. The snippet iterates and recurses the array, appending the keys as it recurses. static allows the reuse/build of $output.
I have two arrays I want to compare these two arrays and find the match. If 807 and 200 appears in same keys like 131 then create third array
array(131=>(807,200));
array1:-
Array([0] => 807,[1] => 200)
array2 :-
$mat= Array([0] => Array([131] => 807),[1] => Array([132] => 807),[2] => Array([125] => 200),[3] => Array([131] => 200))
My code:
<?php
$filtered = array();
array_walk_recursive($matchingskusarr, function($val, $key) use(&$filtered) {
if ($key === 131) {
echo "The key $key has the value $val<br>";
$filtered[$val] = $key;
}
});
echo "<pre>";
print_r($filtered);
echo "</pre>";
?>
You can use array_column like this:
$filtered = array_column($mat, 131);
//Output: Array ( [0] => 807 [1] => 200 )
Update 1:
$matchingskusarr = Array( 0 => Array(131 => 807), 1 => Array(132 => 807),2 => Array(125 => 200),3 => Array(131 => 200)) ;
$skus = array(0=>807, 1=>200);
function yourMatch($skus, $matchingskusarr) {
$continue = [];
foreach ($matchingskusarr as $array) {
//Get the first key !!!
foreach ($array as $key => $value);
//Column already tested just continue
if(isset($continue[$key])) {
continue;
}
//New column we need to check if it matches our $skus
$column = array_column($matchingskusarr, $key);
if($column == $skus) {
return [$key => $column ];
}
$continue[$key] = true;
}
return null;
}
print_r(yourMatch($skus, $matchingskusarr));
Demo: https://3v4l.org/Cr2L4
I have an array, looking like this:
[lund] => Array
(
[69] => foo
)
[berlin] => Array
(
[138] => foox2
)
[tokyo] => Array
(
[180] => foox2
[109] => Big entrance
[73] => foo
)
The thing is that there were duplicate keys, so I re-arranged them so I can search more specifically, I thought.
Previously I could just
$key = array_search('foo', $array);
to get the key but now I don't know how.
Question: I need key for value foo, from tokyo. How do I do that?
You can get all keys and value of foo by using this:
foreach ($array as $key => $value) {
$newArr[$key] = array_search('foo', $value);
}
print_r(array_filter($newArr));
Result is:
Array
(
[lund] => 69
[tokyo] => 109
)
If you don't mind about the hard code than you can use this:
array_search('foo', $array['tokyo']);
It just a simple example, you can modify it as per your requirement.
Try this
$a = array(
"land"=> array("69"=>"foo"),
"land1"=> array("138"=>"foo1"),
"land2"=> array('180' => 'foox2',
'109' => 'Big entrance',
'73' => 'foo'),
);
//print_r($a);
$reply = search_in_array($a, "foo");
print_r($reply);
function search_in_array($a, $search)
{
$result = array();
foreach($a as $key1 => $array ) {
foreach($array as $k => $value) {
if($value == "$search") {
array_push($result,"{$key1}=>{$k}");
breck;
}
}
}
return $result;
}
This function will return the key or null if the search value is not found.
function search($searchKey, $searchValue, $searchArr)
{
foreach ($searchArr as $key => $value) {
if ($key == $searchKey && in_array($searchValue, $value)) {
$results = array_search($searchValue, $value);
}
}
return isset($results) ? $results : null;
}
// var_dump(search('tokyo', 'foo', $array));
Since Question: I need key for value foo, from tokyo. How do i do that?
$key = array_search('foo', $array['tokyo']);
As a function:
function getKey($keyword, $city, $array) {
return array_search($keyword, $array[$city]);
}
// PS. Might be a good idea to wrap this array in an object and make getKey an object method.
If you want to get all cities (for example to loop through them):
$cities = array_keys($array);
I created solution using array iterator. Have a look on below solution:
$array = array(
'lund' => array
(
'69' => 'foo'
),
'berlin' => array
(
'138' => 'foox2'
),
'tokyo' => array
(
'180' => 'foox2',
'109' => 'Big entrance',
'73' => 'foo'
)
);
$main_key = 'tokyo'; //key of array
$search_value = 'foo'; //value which need to be search
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach ($iterator as $key => $value) {
$keys = array();
if ($value == $search_value) {
$keys[] = $key;
for ($i = $iterator->getDepth() - 1; $i >= 0; $i--) {
$keys[] = $iterator->getSubIterator($i)->key();
}
$key_paths = array_reverse($keys);
if(in_array($main_key, $key_paths) !== false) {
echo "'{$key}' have '{$value}' value which traverse path is: " . implode(' -> ', $key_paths) . '<br>';
}
}
}
you can change value of $main_key and $serch_value according to your parameter. hope this will help you.
<?php
$lund = [
'69' => 'foo'
];
$berlin = [
'138' => 'foox2'
];
$tokyo = [
'180' => 'foox2',
'109' => 'Big entrance',
'73' => 'foo'
];
$array = [
$lund,
$berlin,
$tokyo
];
echo $array[2]['180']; // outputs 'foox2' from $tokyo array
?>
If you want to get key by specific key and value then your code should be:
function search_array($array, $key, $value)
{
if(is_array($array[$key])) {
return array_search($value, $array[$key]);
}
}
echo search_array($arr, 'tokyo', 'foo');
try this:
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 'On');
$array=array("lund" => array
(
69 => "foo"
),
"berlin" => array
(
138 => "foox2"
),
"tokyo" => array
(
180 => "foox2",
109 => "Big entrance",
73 => "foo"
));
function search($array, $arrkey1, $arrvalue2){
foreach($array as $arrkey=>$arrvalue){
if($arrkey == $arrkey1){
foreach($arrvalue as $arrkey=>$arrvalue){
if(preg_match("/$arrvalue/i",$arrvalue2))
return $arrkey;
}
}
}
}
$result=search($array, "tokyo", "foo"); //$array=array; tokyo="inside array to check"; foo="value" to check
echo $result;
You need to loop through array, since its 2 dimensional in this case. And then find corresponding value.
foreach($arr as $key1 => $key2 ) {
foreach($key2 as $k => $value) {
if($value == "foo") {
echo "{$k} => {$value}";
}
}
}
This example match key with $value, but you can do match with $k also, which in this case is $key2.