This question already has answers here:
How to Flatten a Multidimensional Array?
(31 answers)
Closed 5 months ago.
I have following array keys values:
$arrData = array
(
array(
'a' => 'test',
'c' => 1,
'd' => 2,
'e' => 'B'
),
array(
'c' => 1,
'd' => 2,
'e' => 'B'
),
array(
'b' => 'test2',
'c' => 1,
'd' => 2,
'e' => 'B'
)
);
So here I need to merged array into single with combining missing keys with single value array.
Can someone please help to get following output in single array?
$arrData = array
(
array(
'a' => 'test',
'b' => 'test2',
'c' => 1,
'd' => 2,
'e' => 'B'
)
);
Thanking in advance!
Just merge them and then sort on the key:
$arrData = array_merge(...$arrData);
ksort($arrData);
Instead of ... you can use:
$arrData = call_user_func_array('array_merge', $arrData);
If you really want the result to be multi-dimensional, then:
$arrData = [$arraData];
//or
$arrData = array($arrData);
You can use array_reduce (or a simple foreach loop) to merge each of the subsequent array values with the first one:
$out = array_reduce($arrData, function ($c, $v) { return array_merge($c, $v); }, array());
print_r($out);
$out = array();
foreach ($arrData as $arr) {
$out = array_merge($out, $arr);
}
print_r($out);
Output (for both examples):
Array (
[a] => test
[c] => 1
[d] => 2
[e] => B
[b] => test2
)
If you want to keep the keys in alphabetical order, you can use ksort:
ksort($out);
print_r($out);
Array (
[a] => test
[b] => test2
[c] => 1
[d] => 2
[e] => B
)
Demo on 3v4l.org
Using array_walk and ksort
$res=[];
array_walk($arrData, function($v,$k) use(&$res){
$res = array_merge($res,$v);
});
ksort($res);
OR
You can use foreach and array_column
$keys = ['a','b','c','d','e'];
$res=[];
foreach($keys as $val){
$res[$val] = array_column($arrData, $val)[0];
}
print_r($res);
Live Demo
<?php
$arrData = array
(
array(
'a' => 'test',
'c' => 1,
'd' => 2,
'e' => 'B'
),
array(
'c' => 1,
'd' => 2,
'e' => 'B'
),
array(
'b' => 'test2',
'c' => 1,
'd' => 2,
'e' => 'B'
)
);
$result_array = array();
foreach($arrData as $ad){
foreach($ad as $key=>$value){
if(!array_key_exists($key,$result_array)){
$result_array[$key] = $value;
}
}
}
print_r($result_array);
?>
Related
This question already has an answer here:
Convert value from specific multidimensional array key into key in new array with original arrays as value
(1 answer)
Closed 5 months ago.
What's the easiest way to convert
$a = array(
array("id" => 1, "name" => "a1"),
array("id" => 2, "name" => "a2")
);
to
$b = array(
"a1" => array("id" => 1, "name" => "a1"),
"a2" => array("id" => 2, "name" => "a2")
);
I was expecting PHP have some functional programming facilities to do something like:
$b = map($a, function($item) {
return $item["name"];
});
But I didn't find one.
You can use PHP array_column() function. For your use case, the second argument should be null to return the full array.
$a = array(
array("id" => 1, "name" => "a1"),
array("id" => 2, "name" => "a2")
);
$b = array_column($a, null, 'name');
and print_r($b) will result in
Array
(
[a1] => Array
(
[id] => 1
[name] => a1
)
[a2] => Array
(
[id] => 2
[name] => a2
)
)
The only solution I see is to loop through the array and create a new array manually.
For example, like this:
$new_array = [];
foreach ($array as $value)
$new_array[$value['name']] = $value;
You can simply do this
$input = [
["id" => 1, "name" => "a1"],
["id" => 2, "name" => "a2"]
];
$result = array_merge(
...array_map(
fn($item) => [$item['name'] => $item],
$input
)
);
Poor me need to implement this in PHP 5.2, and I do not want to use for loop
here's my implementation:
function getField($x) { return $x['name']; }
$ids = array_map('getField', $result);
$result = array_combine($ids, $result);
See if maybe this helps anybody lol
The accepted answer is close, but "close" only counts with hand grenades.
($unique is an indexed array)
$sub_key = 'country';
$new_array = [];
foreach ($unique as $value) {
$new_array[] = [$sub_key => $value];
}
How about:
$a = array(
array('a' => 'a0', 'b' => 'b0', 'c' => 'c0'),
array('a' => 'a1', 'b' => 'b1', 'c' => 'c1'),
array('a' => 'a2', 'b' => 'b2', 'c' => 'c2'),
);
print_r($a);
print_r(array_combine(array_column($a, 'a'), $a));
Where 'a' is the column to use as the associative index.
This leaves the column that becomes the index in the array.
array_column (PHP 5 >= 5.5.0, PHP 7)
array_combine (PHP 5, PHP 7)
This question already has answers here:
Merge row data from multiple arrays
(6 answers)
Closed 5 months ago.
Now I have an array looks like this
Array([0] => array([region]=>1[district]=>2[sell]=>3)
[1] => array([region]=>1[district]=>3[sell]=>6)
[2] => array([region]=>1[district]=>4[sell]=>9)
)
And I have an other array look like this
Array([0] => array([buy]=>3)
[1] => array([buy]=>4)
[2] => array([buy]=>5)
)
So the question is how can i combine two array to make it looks like this ?
or is there any method to push the second array into the first array?
Array([0] => array([region]=>1[district]=>2[sell]=>3[buy]=>3)
[1] => array([region]=>1[district]=>3[sell]=>6[buy]=>4)
[2] => array([region]=>1[district]=>3[sell]=>9[buy]=>5)
)
Do not forget about functional programming.
$existing = [
['a' => 1, 'b' => 2, 'c' => 3],
['a' => 4, 'b' => 5, 'c' => 6],
['a' => 5, 'b' => 8, 'c' => 9],
];
$newItems = [
['d' => 3],
['d' => 4],
['d' => 5]
];
// let's run over those arrays and do array_merge over items
$result = array_map('array_merge', $existing, $newItems);
var_dump($result);
P.S. There is exist more simple way using array_replace_recursive
$result2 = array_replace_recursive($existing, $newItems);
Try this
$existing = array(
0 => array('region'=>1, 'district'=>2, 'sell'=>3),
1 => array('region'=>4, 'district'=>5, 'sell'=>6),
2 => array('region'=>5, 'district'=>8, 'sell'=>9),
);
$newItems = array(
0 => array('buy'=>3),
1 => array('buy'=>4),
2 => array('buy'=>5)
);
foreach($newItems as $i => $data){
$key = array_pop(array_keys($data));
$value = array_pop(array_values($data));
$existing[$i][$key] = $value;
}
echo '<pre>'; print_r($existing); echo '</pre>';
PhpFiddle Demo
I have an initial array:
$arr0 = array(
0 => array(
'a' => 1,
'b' => 1
)
1 => array(
'a' => 2,
'b' => 1
)
2 => array(
'a' => 3,
'b' => 2
)
3 => array(
'a' => 4,
'b' => 3
)
4 => array(
'a' => 5,
'b' => 3
)
);
I wish to divide it into separate arrays depending on its members' value of the field 'b', like so:
// $arr1 contains $arr0[0] and $arr0[1] because their value of 'b' is 1.
$arr1 = array(
0 => array(
'a' => 1,
'b' => 1
)
1 => array(
'a' => 2,
'b' => 1
)
);
// $arr2 contains $arr0[2] because its value of 'b' is 2.
$arr2 = array(
0 => array(
'a' => 3,
'b' => 2
)
);
// $arr3 contains $arr0[3] and $arr0[4] because their value of 'b' is 3.
$arr3 = array(
0 => array(
'a' => 4,
'b' => 3
)
1 => array(
'a' => 5,
'b' => 3
)
);
Now, the field 'b' can have any natural number for value, so it is not always three resulting arrays that I will need.
I have found a related question (and answers) here, but my problem is specific because I don't know in advance what original values 'b' has, and how many of different values there are.
Any ideas?
(edit: $arr3 was written as $arr1)
foreach ($arr0 as $value) {
${"arr" . $value['b']}[] = $value;
}
// $arr1, $arr2 and $arr3 are defined
There is magic in the second line, which dynamically builds a variable name. However, that way of programming is really unwieldy; you would do better to make the results into yet another array, like this:
foreach ($arr0 as $value) {
$allarr[$value['b']][] = $value;
}
// $allarr is defined
foreach ($arr0 as $val) {
$b = $val ['b'];
if (!$arr$b) $arr$b = array();
$arr$b[] = $val;
}
This question already has answers here:
Change array key without changing order
(8 answers)
Closed 7 years ago.
How i can do this:
$array = array('a' => 1, 'd' => 2, 'c' => 3); //associative array
// rename $array['d'] as $array['b']
$array = replace_key_function($array, 'd', 'b');
var_export($array); // array('a' => 1, 'b' => 2, 'c' => 3); same order!
I didn't see a function that does that.
There is a way to do this?
http://ideone.com/nCZnY
$array = array('a' => 1, 'd' => 2, 'c' => 3); //associative array
// rename $array['d'] as $array['b']
$array = replace_key_function($array, 'd', 'b');
var_export($array); // array('a' => 1, 'b' => 2, 'c' => 3); same order!
function replace_key_function($array, $key1, $key2)
{
$keys = array_keys($array);
$index = array_search($key1, $keys);
if ($index !== false) {
$keys[$index] = $key2;
$array = array_combine($keys, $array);
}
return $array;
}
There is a flaw in the logic of the accepted answer.
If you have an array like this:
[
'k1'=>'k1',
'k2'=>'k2',
'k3',
'k4'=>'k4'
]
and replace 'k4' with 'something' you will get an output like this:
[
'k1'=>'k1',
'k2'=>'k2',
'something' => 'k3',
'k4'=>'k4'
]
Here is a quick fix that solves the problem:
function replace_key_function($array, $key1, $key2)
{
$keys = array_keys($array);
//$index = array_search($key1, $keys);
$index = false;
$i = 0;
foreach($array as $k => $v){
if($key1 === $k){
$index = $i;
break;
}
$i++;
}
if ($index !== false) {
$keys[$index] = $key2;
$array = array_combine($keys, $array);
}
return $array;
}
EDIT:2014/12/03
The accepted answer does work if you set the third parameter (strict) of array_search to true.
Instead of using loops, you could always flatten to string with json_encode(), perform a string replacement, then json_decode() back to an array:
function replaceKey($array, $old, $new)
{
//flatten the array into a JSON string
$str = json_encode($array);
// do a simple string replace.
// variables are wrapped in quotes to ensure only exact match replacements
// colon after the closing quote will ensure only keys are targeted
$str = str_replace('"'.$old.'":','"'.$new.'":',$str);
// restore JSON string to array
return json_decode($str, TRUE);
}
Now this doesn't check for conflicts with pre-existing keys (easy enough to add a string comparison check), and it might not be the best solution for single replacements in massive arrays.. but the nice part about flattening the array into a string for replacement is that it effectively makes replacement recursive since matches at any depth are all replaced in one pass:
$arr = array(
array(
'name' => 'Steve'
,'city' => 'Los Angeles'
,'state' => 'CA'
,'country' => 'USA'
,'mother' => array(
'name' => 'Jessica'
,'city' => 'San Diego'
,'state' => 'CA'
,'country' => 'USA'
)
)
,array(
'name' => 'Sara'
,'city' => 'Seattle'
,'state' => 'WA'
,'country' => 'USA'
,'father' => array(
'name' => 'Eric'
,'city' => 'Atlanta'
,'state' => 'GA'
,'country' => 'USA'
,'mother' => array(
'name' => 'Sharon'
,'city' => 'Portland'
,'state' => 'OR'
,'country' => 'USA'
)
)
)
);
$replaced = replaceKey($arr,'city','town');
print_r($replaced);
outputs
Array
(
[0] => Array
(
[name] => Steve
[town] => Los Angeles
[state] => CA
[country] => USA
[mother] => Array
(
[name] => Jessica
[town] => San Diego
[state] => CA
[country] => USA
)
)
[1] => Array
(
[name] => Sara
[town] => Seattle
[state] => WA
[country] => USA
[father] => Array
(
[name] => Eric
[town] => Atlanta
[state] => GA
[country] => USA
[mother] => Array
(
[name] => Sharon
[town] => Portland
[state] => OR
[country] => USA
)
)
)
)
A generic and simple solution with PHP 5.3+ using array_walk:
$array = array('a' => 1, 'd' => 2, 'c' => 3); //associative array
$array = replace_keys($array, array('d' => 'b'));
var_export($array); // array('a' => 1, 'b' => 2, 'c' => 3); same order!
function replace_keys(array $source, array $keyMapping) {
$target = array();
array_walk($source,
function ($v, $k, $keyMapping) use (&$target) {
$mappedKey = isset($keyMapping[$k]) ? $keyMapping[$k] : $k;
$target[$mappedKey] = $v;
},
$keyMapping);
return $target;
}
a good answer has been posted, but here's my two pence:
$array = array('a'=>1, 'd'=>2, 'c'=>3);
// rename 'd' to 'b'
foreach($array as $k=>$v){
if($k == 'd') { $k='b'; }
$newarray[$k] = $v;
}
$array = $newarray;
in response to mike-purcell would this be a more accepted approach to my example above?
changeKey($array, 'd', 'b');
function changeKey($array, $oldKey, $newKey)
{
foreach($array as $k=>$v){
if($k == $oldKey) { $k = $newKey; }
$returnArray[$k] = $v;
}
return $returnArray;
}
I'm always looking to improve :)
I have array as follows
array (A => 1)
array (A => 1, B=>2)
array (A => 1, B=>2, C=>3)
array (A => 1, D=>4)
array (A => 1, E=>5)
array (A => 1, F=>6)
array (A => 1, F=>6, G=>8)
array (A => 1, F=>6, H=>9)
array (X => 11)
array (X => 11, Y=22)
array (X => 11, Z=33)
I need to form array as follows
array(A=>array(B=>2, C=>3, D=>4, E=>5, F=>array(G=>8,H=>9))
X=>array(Y=>22, Z=>33)
I think this is what you’re looking for:
$result = array();
foreach ($arrays as $array) {
$ref = &$result;
foreach ($array as $key => $val) {
if (!isset($ref[$key])) {
$ref[$key] = $val;
} elseif (!is_array($ref[$key])) {
$ref[$key] = array();
}
$ref = &$ref[$key];
}
}
Here the keys are interpreted as path segments to walk the array using a reference. If there is no value yet, the value is stored; if there already is a value, it is replaced by an array.
But this is generating a little different result:
array (
'A' =>
array (
'B' =>
array (
'C' => 3,
),
'D' => 4,
'E' => 5,
'F' =>
array (
'G' => 8,
'H' => 9,
),
),
'X' =>
array (
'Y' => 22,
'Z' => 33,
),
)