Find values in multidimensional arrays - php

I've a multidimensional array:
array (
array (
"username" => "foo",
"favoriteGame" => "Mario"
)
array (
"username" => "bar",
"favoriteGame" => "Mario"
)
array (
"username" => "xyz",
"favoriteGame" => "Zelda"
)
)
How could I get the usernames of the persons that like to play for example Mario the easiest way possible?
EDIT:
My fault: forget to explicitly mention that the "favoriteGame" value is dynamic and I cannot know which it is in advance.
My Solution:
foreach($users as $key => $value)
{
if(!isset($$value['favoriteGame']))
{
$$value['favoriteGame'] = array();
}
array_push($$value['favoriteGame'], $value['username']);
}
Iterate over each sub-array and find its favoriteGame value.
If there is not already an array $favoriteGame create it.
Push the username-value of the actual sub-array to the $favoriteGame array.
Thanks for your replies, I just couldn't phrase this question properly.

function getUsernamesByFavoriteGame($data, $game) {
$usernames = array();
foreach($data as $arr) {
if ($arr['favoriteGame'] == $game) {
$usernames[] = $arr['username'];
}
}
return $usernames;
}

$usernames = array();
foreach($array as $key => $value) {
if ($value['favoriteGame'] == 'Mario') {
$usernames[] = $value['username'];
}
}

I would use array_filter. If you have PHP 5.3 or up, you can do it like this:
$favorite = "Mario";
$filter = function($player) use($favorite) { return $player['favoriteGame'] == $favorite; };
$filtered = array_filter($players, $filter);
It will be a little different for older versions because you won't be able to use lambda functions.

$game = 'Mario';
$users = array();
foreach($array as $key => $value) {
if ($value['favoriteGame'] == $game) {
$users[] = $value['username'];
}
}

If you are using this more often then convert the data structure to something like this.
array(
"Mario" => array(
"0":"foo",
"1":"xyz"
)
"Zelda" => array(
"0":"pqr",
"1":"abc"
)
)
This will directly give you list of user names for a favorite game.
$arr[$favGame]
If you cannot change the data structure then go with with tigrang has suggested.

I think you should implement a custom multidimensional search function.
Take a look at this answer.
Here's how you would use it
Code | Live example
function search($array, $key, $value){
$results = array();
if (is_array($array))
{
if (isset($array[$key]) && $array[$key] == $value)
$results[] = $array;
foreach ($array as $subarray)
$results = array_merge($results, search($subarray, $key, $value));
}
return $results;
}
$arr = array (
array (
"username" => "foo",
"favoriteGame" => "Mario"
),
array (
"username" => "bar",
"favoriteGame" => "Mario"
),
array (
"username" => "xyz",
"favoriteGame" => "Zelda"
)
);
print_r(search($arr, 'favoriteGame', 'Mario'));
//OUTPUT
Array (
[0] => Array (
[username] => foo
[favoriteGame] => Mario
)
[1] => Array (
[username] => bar
[favoriteGame] => Mario
)
)

$array = array( 'a' => 'A',
'b'=>'B',
'c'=>'C',
'd'=>array(
'e'=>array(
'f'=>'D'
),
'g'=>array(
'h'=>'E'
)
),
'i'=>'F',
'j'=>array(
'k'=>'G'
),
'l'=>'H'
);
$new_array = array();
foreach($array as $k1=>$v1){
if(is_array($v1)){
$new_array = parseArray($new_array, $k1, $v1);
}else{
$new_array = array_merge($new_array, array($k1=>$v1));
}
}
function parseArray($new_array, $key, $val){
if(is_array($val)){
foreach($val as $k2=>$v2){
if(is_array($v2)){
$new_array = parseArray($new_array, $k2, $v2);
}else{
$new_array = array_merge($new_array, array($k2=>$v2));
}
}
}else{
$new_array = array_merge($new_array, array($key=>$val));
}
return $new_array;
}
Output
Array
(
[a] => A
[b] => B
[c] => C
[f] => D
[h] => E
[i] => F
[k] => G
[l] => H
)

Related

php recursive key renaming for inner arrays only

i am in need of bit direction here for renaming my inner child keys who inner depth is unknown. Original array is parent child multidimensional array created via id and parent_id relation. Here's a one example of array
$testArray = array (
"name" => "Test name",
"someValue1" => 834.69,
"someMoreValue" => 33.4,
"someCode" => 6668,
"child" => array
(
array
(
"name" => "Some name",
"someValue1" => 471.05,
"someMoreValue" => 18.84,
"someCode" => 7064,
"child" => array
(
array
(
"name" => "Yet another name",
"someValue1" => 438.62,
"someMoreValue" => 17.56,
"someCode" => 7065
),
array
(
"name" => "Da name",
"someValue1" => 4444,
"someMoreValue" => 44,
"someCode" => 7044
)
)
),
array
(
"name" => "name",
"someValue1" => 2222,
"someMoreValue" => 22,
"someCode" => 7022
)
)
);
here's my trying so far, i am able to rename the first level of childs only.
function keyprefix($keyprefix, $keyprefix2, Array $array) {
foreach($array as $k=>$v){
$array[$keyprefix.'-'.$k.'-'.$keyprefix2] = $v;
unset($array[$k]);
}
return $array;
}
function test($array) {
$newArr = array();
foreach ($array as $key => $value) {
// $newArr[] = is_array($value) ? test($value) : $value;
// $newArr[] = is_array($value) ? $array : array_merge( keyprefix("$name","Alt Danışman", $array[$key]) );
$index = 0;
$name = $array['name'];
if (is_array($value)) {
//if (is_array($value)) {
// test($value);
//}
$newArr[$key] = array_merge(
keyprefix("$name","Under Child", $array[$key])
);
}
else {
$newArr[$key] = $value;
}
}
return $newArr;
}
echo highlight_string(var_export(test($testArray), true));
Any ideas on how I can approach this? I feel that I am close just need a little guide in the right path. I have seen many examples of stack-overflow etc but need some help. I know recursion is not my best skill yet.
function TryRenameChildren(array $array)
{
if(isset($array['child']))
{
$array['child'] = keyprefix($array['name'], 'prefix2', $array['child']);
foreach($array['child'] as $key => $value)
if(is_array($value))
$array['child'][$key] = TryRenameChildren($value);
}
return $array;
}
$testArray = TryRenameChildren($testArray);

Compare multidimensional array with simple array

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

Search in a multidimensional assoc array

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.

Taking a string of period separated properties and converting it to a json object in php

I'm fairly sure I'm missing something blindingly obvious here but here it goes.
I am working on updating a search function in an application which was running a loop and doing a very large number of sql queries to get object / table relations to one large query that returns everything. However the only way I could think to return relations was period separated, what I am now wanting to do is take the flat array of keys and values and convert it into an associative array to then be jsonified with json_encode.
For example what I have is this...
array(
"ID"=>10,
"CompanyName"=>"Some Company",
"CompanyStatusID"=>2,
"CompanyStatus.Status"=>"Active",
"addressID"=>134,
"address.postcode"=>"XXX XXXX",
"address.street"=>"Some Street"
);
And what I want to turn it into is this...
array(
"ID"=>10,
"CompanyName"=>"Some Company",
"CompanyStatusID"=>2,
"CompanyStatus"=>array(
"Status"=>"Active"
),
"addressID"=>134,
"address"=>array(
"postcode"=>"XXX XXXX",
"street"=>"Some Street"
)
);
Now I'm sure this should be a fairly simple recursive loop but for the life of me this morning I can't figure it out.
Any help is greatly appreciated.
Regards
Graham.
Your function was part way there mike, though it had the problem that the top level value kept getting reset on each pass of the array so only the last period separated property made it in.
Please see updated version.
function parse_array($src) {
$dst = array();
foreach($src as $key => $val) {
$parts = explode(".", $key);
if(count($parts) > 1) {
$index = &$dst;
$i = 0;
$count = count($parts)-1;
foreach(array_slice($parts,0) as $part) {
if($i == $count) {
$index[$part] = $val;
} else {
if(!isset($index[$part])){
$index[$part] = array();
}
}
$index = &$index[$part];
$i++;
}
} else {
$dst[$parts[0]] = $val;
}
}
return $dst;
}
I am sure there is something more elegant, but quick and dirty:
$arr = array(
"ID"=>10,
"CompanyName"=>"Some Company",
"CompanyStatusID"=>2,
"CompanyStatus.Status"=>"Active",
"addressID"=>134,
"address.postcode"=>"XXX XXXX",
"address.street"=>"Some Street"
);
$narr = array();
foreach($arr as $key=>$val)
{
if (preg_match("~\.~", $key))
{
$parts = split("\.", $key);
$narr [$parts[0]][$parts[1]] = $val;
}
else $narr [$key] = $val;
}
$arr = array(
"ID" => 10,
"CompanyName" => "Some Company",
"CompanyStatusID" => 2,
"CompanyStatus.Status" => "Active",
"addressID" => 134,
"address.postcode" => "XXX XXXX",
"address.street" => "Some Street",
"1.2.3.4.5" => "Some nested value"
);
function parse_array ($src) {
$dst = array();
foreach($src as $key => $val) {
$parts = explode(".", $key);
$dst[$parts[0]] = $val;
if(count($parts) > 1) {
$index = &$dst[$parts[0]];
foreach(array_slice($parts, 1) as $part) {
$index = array($part => $val);
$index = &$index[$part];
}
}
}
return $dst;
}
print_r(parse_array($arr));
Outputs:
Array
(
[ID] => 10
[CompanyName] => Some Company
[CompanyStatusID] => 2
[CompanyStatus] => Array
(
[Status] => Active
)
[addressID] => 134
[address] => Array
(
[street] => Some Street
)
[1] => Array
(
[2] => Array
(
[3] => Array
(
[4] => Array
(
[5] => Some nested value
)
)
)
)
)

PHP rename array keys in multidimensional array

In an array such as the one below, how could I rename "fee_id" to "id"?
Array
(
[0] => Array
(
[fee_id] => 15
[fee_amount] => 308.5
[year] => 2009
)
[1] => Array
(
[fee_id] => 14
[fee_amount] => 308.5
[year] => 2009
)
)
foreach ( $array as $k=>$v )
{
$array[$k] ['id'] = $array[$k] ['fee_id'];
unset($array[$k]['fee_id']);
}
This should work
You could use array_map() to do it.
$myarray = array_map(function($tag) {
return array(
'id' => $tag['fee_id'],
'fee_amount' => $tag['fee_amount'],
'year' => $tag['year']
); }, $myarray);
$arrayNum = count($theArray);
for( $i = 0 ; $i < $arrayNum ; $i++ )
{
$fee_id_value = $theArray[$i]['fee_id'];
unset($theArray[$i]['fee_id']);
$theArray[$i]['id'] = $fee_id_value;
}
This should work.
Copy the current 'fee_id' value to a new key named 'id' and unset the previous key?
foreach ($array as $arr)
{
$arr['id'] = $arr['fee_id'];
unset($arr['fee_id']);
}
There is no function builtin doing such thin afaik.
This is the working solution, i tested it.
foreach ($myArray as &$arr) {
$arr['id'] = $arr['fee_id'];
unset($arr['fee_id']);
}
The snippet below will rename an associative array key while preserving order (sometimes... we must). You can substitute the new key's $value if you need to wholly replace an item.
$old_key = "key_to_replace";
$new_key = "my_new_key";
$intermediate_array = array();
while (list($key, $value) = each($original_array)) {
if ($key == $old_key) {
$intermediate_array[$new_key] = $value;
}
else {
$intermediate_array[$key] = $value;
}
}
$original_array = $intermediate_array;
Converted 0->feild0, 1->field1,2->field2....
This is just one example in which i get comma separated value in string and convert it into multidimensional array and then using foreach loop i changed key value of array
<?php
$str = "abc,def,ghi,jkl,mno,pqr,stu
abc,def,ghi,jkl,mno,pqr,stu
abc,def,ghi,jkl,mno,pqr,stu
abc,def,ghi,jkl,mno,pqr,stu;
echo '<pre>';
$arr1 = explode("\n", $str); // this will create multidimensional array from upper string
//print_r($arr1);
foreach ($arr1 as $key => $value) {
$arr2[] = explode(",", $value);
foreach ($arr2 as $key1 => $value1) {
$i =0;
foreach ($value1 as $key2 => $value2) {
$key3 = 'field'.$i;
$i++;
$value1[$key3] = $value2;
unset($value1[$key2]);
}
}
$arr3[] = $value1;
}
print_r($arr3);
?>
I wrote a function to do it using objects or arrays (single or multidimensional) see at https://github.com/joaorito/php_RenameKeys.
Bellow is a simple example, you can use a json feature combine with replace to do it.
// Your original array (single or multi)
$original = array(
'DataHora' => date('YmdHis'),
'Produto' => 'Produto 1',
'Preco' => 10.00,
'Quant' => 2);
// Your map of key to change
$map = array(
'DataHora' => 'Date',
'Produto' => 'Product',
'Preco' => 'Price',
'Quant' => 'Amount');
$temp_array = json_encode($original);
foreach ($map AS $k=>$v) {
$temp_array = str_ireplace('"'.$k.'":','"'.$v.'":', $temp);
}
$new_array = json_decode($temp, $array);
Multidimentional array key can be changed dynamically by following function:
function change_key(array $arr, $keySetOrCallBack = [])
{
$newArr = [];
foreach ($arr as $k => $v) {
if (is_callable($keySetOrCallBack)) {
$key = call_user_func_array($keySetOrCallBack, [$k, $v]);
} else {
$key = $keySetOrCallBack[$k] ?? $k;
}
$newArr[$key] = is_array($v) ? array_change_key($v, $keySetOrCallBack) : $v;
}
return $newArr;
}
Sample Example:
$sampleArray = [
'hello' => 'world',
'nested' => ['hello' => 'John']
];
//Change by difined key set
$outputArray = change_key($sampleArray, ['hello' => 'hi']);
//Output Array: ['hi' => 'world', 'nested' => ['hi' => 'John']];
//Change by callback
$outputArray = change_key($sampleArray, function($key, $value) {
return ucwords(key);
});
//Output Array: ['Hello' => 'world', 'Nested' => ['Hello' => 'John']];
I have been trying to solve this issue for a couple hours using recursive functions, but finally I realized that we don't need recursion at all. Below is my approach.
$search = array('key1','key2','key3');
$replace = array('newkey1','newkey2','newkey3');
$resArray = str_replace($search,$replace,json_encode($array));
$res = json_decode($resArray);
On this way we can avoid loop and recursion.
Hope It helps.

Categories