Reduce Multidimensional Array Into One Array - php

Simply to said I need help, how to make multidimension array into one array without change the key array?
From these :
Array
(
[0] => Array
(
[554] => a
)
[1] => Array
(
[561] => b
)
[2] => Array
(
[574] => c
)
)
Into these :
Array
(
[554] => a
[561] => b
[574] => c
)

I like to use array_walk_recursive for problems like this:
function flatten($array)
{
$temp=array();
array_walk_recursive($array, function($item, $key) use (&$temp) {
$temp[$key]=$item;
});
return $temp;
}
$a = array(
array(
564=>'a',
),
array(
561=>'b',
array(
562=>'d',
array(
563=>'e',
),
),
),
array(
574=>'c',
),
);
$b = flatten($a);
print_r($b);
This is my output:
Array
(
[564] => a
[561] => b
[562] => d
[563] => e
[574] => c
)

I'll just have to post this, since all the other current answers are so terrifically overcomplicated:
$result = array_reduce($array, function ($result, $array) { return $result + $array; }, array());
That's all that's needed.

i hope i can help you, first of all and do not take this wrong, you have got to investigate a little further, before asking for solutions, i strongly recommend you to go to www.php.net , http://php.net/manual/en/book.array.php and search for array documentation, enough said you are looking at ways to loop through array, actually you are looking for the "foreach" statement, here i have made a simple solution which you can convert into function later:
<?php
$original = array
(
0 => array(554 => 'a'),
1 => array(561 => 'b'),
2 => array(574 => 'c'),
);
/*$result = Array
(
[554] => a
[561] => b
[574] => c
);*/
$result = array();
foreach ($original as $sub_array) {
//this help us read first level array
foreach ($sub_array as $subArrayKey=>$subArray) {
// this help us read second level array
$result[$subArrayKey] = $subArray;
}
}
echo '<pre>';
print_r($result);
echo '</pre>';
?>

This should work for you:
$array = array(
array(554 => "a"),
array(561 => "b"),
array(574 => "c")
);
function getL2Keys($array) {
foreach($array as $sub)
$result[] = array_keys($sub);
return call_user_func_array('array_merge', array_values($result));
}
$array = array_combine(getL2Keys($array), call_user_func_array('array_merge', array_values($array)));
print_r($array);
Output:
Array
(
[554] => a
[561] => b
[574] => c
)

Related

How to remove null values in multi-dimensional array?

I want to remove null values from this array.
Array(
[0] => Array( [fcmToken] => 123 )
[1] => Array( [fcmToken] => )
[2] => Array( [fcmToken] => 789 )
)
Expected Results
Array(
[0] => Array( [fcmToken] => 123 )
[1] => Array( [fcmToken] => 789 )
)
Here we are using foreach to iterate over values and using $value for non-empty $value["fcmToken"]
$result=array();
foreach($array as $key => $value)
{
if(!empty($value["fcmToken"]))
{
$result[]=$value;
}
}
print_r($result);
Output:
Array
(
[0] => Array
(
[fcmToken] => dfqVhqdqhpk
)
[1] => Array
(
[fcmToken] => dfgdfhqdqhpk
)
)
Use array_filter with a callback:
$r = array_filter($array, function($v) { return !empty($v['fcmToken']); });
For checking exactly null:
$r = array_filter($array, function($v) { return !is_null($v['fcmToken']); });
The best and easy single line solution for filter multidimensional array like below.
$aryMain = array_filter(array_map('array_filter', $aryMain));
I hope this solution is work for you. for more detail please visit below link.
PHP: remove empty array strings in multidimensional array
Danger! Do not trust empty() when dealing with numbers (or number-ish) values that could be zero!!! The same is true with using array_filter without a specific filtering parameter (as several answers on this page are using).
Look at how you can get the wrong output:
Bad Method:
$array = array(
array("fcmToken" => '0'),
array("fcmToken" => 123),
array("fcmToken" => ''),
array("fcmToken" => 789),
array("fcmToken" => 0)
);
$result=array(); // note, this line is unnecessary
foreach($array as $key => $value){ // note, $key is unnecessary
if(!empty($value["fcmToken"])){ // this is not a reliable method
$result[]=$value;
}
}
var_export($result);
Output:
array (
0 =>
array (
'fcmToken' => 123,
),
1 =>
array (
'fcmToken' => 789,
),
)
The zeros got swallowed up!
This is how it should be done:
Instead, you should use strlen() to check the values:
Method #1: foreach()
foreach($array as $sub){
if(strlen($sub["fcmToken"])){
$result[]=$sub;
}
}
var_export($result);
Method #2: array_filter() w/ anonymous function and array_values() for consistency
var_export(array_values(array_filter($array,function($a){return strlen($a['fcmToken']);})));
Output for either method:
array (
0 =>
array (
'fcmToken' => '0',
),
1 =>
array (
'fcmToken' => 123,
),
2 =>
array (
'fcmToken' => 789,
),
3 =>
array (
'fcmToken' => 0,
),
)
Demonstration of bad method and two good methods.
You need to do it using array_map, array_filter and array_values. Check below code :
$entry = array(
array("fcmToken" => 'dfqVhqdqhpk'),
array("fcmToken" => ''),
array("fcmToken" => 'dfgdfhqdqhpk'),
);
echo "<pre>";
$entry = array_values(array_filter(array_map('array_filter', $entry)));
print_r($entry);
Use this recursive function which iterates over any subarray and remove all elements with a null-value.
function removeNullValues ($array) {
foreach ($array as $key => $entry) {
if (is_array($entry)) {
$array[$key] = removeNullValues($entry);
if ($array[$key] === []) {
unset($array[$key]);
}
} else {
if ($entry === null) {
unset($array[$key]);
}
}
}
return $array;
}
Try using array_map() to apply the filter to every array in the array.

Find the difference from two arrays in php

--$arr1----
Array
(
[0] => Array
(
[id] => 1
[Name] => AAA
)
[1] => Array
(
[id] => 6
[Name] => BBB
)
)
--$arr2---
Array
(
[0] => Array
(
[id] => 1
[Name] => AAA
)
[1] => Array
(
[id] => 6
[Name] => BBB
)
[2] => Array
(
[id] => 46
[Name] => CCC
)
)
I would like the final result as following. Is there anyone can help me?
--Final Result--
Array
(
[0] => Array
(
[id] => 46
[Name] => CCC
)
)
UPDATE---
In this case, the result of array_diff($arr1,$arr2) is empty.
The easiest way is Mark Baker's solution or just write your own simple function:
Code:
function arrdiff($a1, $a2) {
$res = array();
foreach($a2 as $a) if (array_search($a, $a1) === false) $res[] = $a;
return $res;
}
print_r(arrdiff($arr1, $arr2));
Output:
Array
(
[0] => Array
(
[id] => 46
[name] => CCC
)
)
$arr1 = array(array('id' => 1, 'Name' => 'AAA'),
array('id' => 6, 'Name' => 'BBB')
);
$arr2 = array(array('id' => 1, 'Name' => 'AAA'),
array('id' => 6, 'Name' => 'BBB'),
array('id' => 46, 'Name' => 'CCC')
);
$results = array_diff(array_map('serialize',$arr2),array_map('serialize',$arr1));
$results = array_map('unserialize',$results);
var_dump($results);
EDIT
And just for the sheer fun of it, you could use array_filter() instead of array_diff() - which means no need to serialize anything at all
$results = array_filter($arr2, function ($value) use($arr1) { return !in_array($value,$arr1); } );
var_dump($results);
You should use array_diff():
$finalResult = array_diff($arr2, $arr1);
If you need more complex comparison you may also build foreach loop and use like this:
function compareItems( $a, $b){
return $a['id'] == $b['id']; // Example compare criteria
}
$result = array();
foreach( $arr1 as $item){
foreach( $arr2 as $key => $it){
if( !compareItems( $item, $it)){
$result[] = $it; // Either build new array
unset( $arr2[$key]); // Or remove items from original array
break;
}
}
}
And than you'll probably want to implement the same with reversed order of $arr1 and $arr2.
You can solve this with array_udiff()
function arr_comp($a, $b)
{
if ($a['id'] == $b['id'])
return 0;
else if ($a['id'] > $b['id'])
return 1;
else
return -1;
}
$result = array_udiff($arr2, $arr1, 'arr_comp');
or if you don't know in which array the differences may be you can try:
$res1 = array_udiff($arr1, $arr2, 'arr_comp');
$res2 = array_udiff($arr2, $arr1, 'arr_comp');
$result = array_merge($res1, $res2);
$arrDif=array();
$i=0;
foreach($arr1 as $value)
{
if(!in_array($value, $arr2))
{
$arrDif[$i]=$value;
$i++;
}
}
Take a look at the PHP built-in function array_diff. That'll help you out :-) Just pass your two arrays, and store the array returned by array_diff(), which will contain the differences between the two arrays.
As you're using multi-dimensional arrays, look at this comment on the PHP website: http://www.php.net/manual/en/function.array-diff.php#98680.

Count number of different strings?

I have an array that looks like
Array
(
[1] => Array
(
[0] => Date
[1] => Action
)
[2] => Array
(
[0] => 2011-01-22 11:23:19
[1] => SHARE_TWEET
)
[3] => Array
(
[0] => 2011-01-22 11:23:19
[1] => SHARE_FACEBOOK
)
and many other different values (about 10), what I want to do is I want to count the number of times a string is in the array. I was going to use array_count_values but it doesn't count multidimensional arrays.
Any other options?
This could be done by first flattening the array, and then using array_count_values() on it:
For flattening, here is the trick:
$array = call_user_func_array('array_merge', $arrays);
And then:
$counts = array_count_values($array);
Output:
array (
'Date' => 1,
'Action' => 1,
'2011-01-22 11:23:19' => 2,
'SHARE_TWEET' => 1,
'SHARE_FACEBOOK' => 1,
)
Full code:
$array = call_user_func_array('array_merge', $arrays);
var_export(array_count_values($array));
Any time you're dealing with arrays, especially with loops in PHP I can't string enough suggest you look at the array documentation, You'd be suprised how quickly you realise most of the loops in your code is unnecessary. PHP has a built in function to achieve what you're after called array_walk_recursive. And since you're using PHP5 you can use closures rather that create_function (which can be very troublesome, especially to debug, and can't be optimised by the PHP interpreter afik)
$strings = array();
array_walk_recursive($arr, function($value, $key) use (&$strings) {
$strings[$value] = isset($strings[$value]) ? $strings[$value]+1 : 1;
});
I know, unary statements aren't always clear, but this one is simple enough, but feel free to expand out the if statement.
The result of the above is:
print_r($strings);
Array
(
[Date] => 1,
[Action] => 1,
[2011-01-22 11:23:19] => 2,
[SHARE_TWEET] => 1,
[SHARE_FACEBOOK] => 1,
)
Pseudo Code
$inputArray = // your array as in the example above
foreach ($inputArray as $key => $value) {
$result[$value[1]] = $result[$value[1]] + 1;
}
var_dump($result);
Here is a way to do the job:
$arr = Array (
1 => Array (
0 => 'Date',
1 => 'Action'
),
2 => Array (
0 => '2011-01-22 11:23:19',
1 => 'SHARE_TWEET'
),
3 => Array (
0 => '2011-01-22 11:23:19',
1 => 'SHARE_FACEBOOK'
)
);
$result = array();
function count_array($arr) {
global $result;
foreach($arr as $k => $v) {
if (is_array($v)) {
count_array($v);
} else {
if (isset($result[$v])) {
$result[$v]++;
} else {
$result[$v] = 1;
}
}
}
}
count_array($arr);
print_r($result);
output:
Array
(
[Date] => 1
[Action] => 1
[2011-01-22 11:23:19] => 2
[SHARE_TWEET] => 1
[SHARE_FACEBOOK] => 1
)

array conversion in php

how would you convert this array:
Array
(
[0] => Array
(
[Contact] => Array
(
[number] => 0425 234 634
)
)
[1] => Array
(
[Contact] => Array
(
[number] => 2939 492 235
)
)
)
into this array
Array
(
[0] => 0425 234 634
[1] => 2939 492 235
)
?
See Set::extract() It uses xpath notation to extract node values from paths in arrays.
$numbers = Set::extract('/Contact/number', $numbers);
Achieve all this in 1 line in far more understandable code than other examples suggested here.
A very dirty method, don't think there is a function to do this for you though.
foreach($array1 as $key => $value) {
$array2[$key]=$value['contact']['number'];
}
EDIT:
Actually, array_values might be of some help, would be worth testing it against your multi-dimensional array.
Since you are using CakePHP, there is an included utility library that does just what you need.
$a = array(
0 => array(
'Contact' => array(
'number' => "0425 234 634"
)
),
1 => array(
'Contact' => array(
'number' => "2939 492 235"
)
)
);
$b = Set::classicExtract($a, '{n}.Contact.number');
print_r($b);
And the result is:
Array
(
[0] => 0425 234 634
[1] => 2939 492 235
)
I've only seen solutions using a seperate array to store the results, this would work just as fine:
<?php
foreach($numbers as $key => $number) {
$numbers[$key] = $number['Contact']['number'];
}
?>
Here you go, fully functional and without any assumptions about your original array :)
<?php
$array = array(
0 => array(
'Contact' => array(
'number' => 123123123
)
),
1 => array(
'Contact' => array(
'number' => 123123123
)
),
2 => array(
'Contact' => array(
'number' => 123123123
)
),
);
function flattenArray(array $arr, &$newArr) {
while($array = array_shift($arr)) {
if(is_array($array)) {
flattenArray($array, $newArr);
} else {
$newArr[] = $array;
}
}
}
$newArr = array();
foreach($array as $key => $value) {
flattenArray($value, $newArr);
}
class DeepCollect {
protected $arr = array();
public function collect($item, $key) {
$this->arr[] = $item;
}
public static function collect_all($array) {
$collect = new self;
array_walk_recursive($array, array($collect, "collect"));
return $collect->arr;
}
}
print_r(DeepCollect::collect_all($input_array));
Will work for any nested-array irrespective of key combinations.
This should work also with
Set:extract( "{n}.Contact.number", $a );
Set::extract( "/number", $a );

How can I merge PHP arrays?

I have two arrays of animals (for example).
$array = array(
array(
'id' => 1,
'name' => 'Cat',
),
array(
'id' => 2,
'name' => 'Mouse',
)
);
$array2 = array(
array(
'id' => 2,
'age' => 321,
),
array(
'id' => 1,
'age' => 123,
)
);
How can I merge the two arrays into one by the ID?
#Andy
http://se.php.net/array_merge
That was my first thought but it doesn't quite work - however array_merge_recursive might work - too lazy to check right now.
This does what Erik suggested (id no. as array key) and merges vlaues in $array2 to $results.
$results = array();
foreach($array as $subarray)
{
$results[$subarray['id']] = array('name' => $subarray['name']);
}
foreach($array2 as $subarray)
{
if(array_key_exists($subarray['id'], $results))
{
// Loop through $subarray would go here if you have extra
$results[$subarray['id']]['age'] = $subarray['age'];
}
}
First off, why don't you use the ID as the index (or key, in the mapping-style array that php arrays are imo)?
$array = array(
1 => array(
'name' => 'Cat',
),
2 => array(
'name' => 'Mouse',
)
);
after that you'll have to foreach through one array, performing array_merge on the items of the other:
foreach($array2 as $key=>$value) {
if(!is_array($array[$key])) $array[$key] = $value;
else $array[$key] = array_merge($array[key], $value);
}
Something like that at least. Perhaps there's a better solution?
<?php
$a = array('a' => '1', 'b' => array('t' => '4', 'g' => array('e' => '8')));
$b = array('c' => '3', 'b' => array('0' => '4', 'g' => array('h' => '5', 'v' => '9')));
$c = array_merge_recursive($a, $b);
print_r($c);
?>
array_merge_recursive — Merge two or more arrays recursively
outputs:
Array
(
[a] => 1
[b] => Array
(
[t] => 4
[g] => Array
(
[e] => 8
[h] => 5
[v] => 9
)
[0] => 4
)
[c] => 3
)
#Andy
I've already looked at that and didn't see how it can help merge multidimensional arrays. Maybe you could give an example.
#kevin
That is probably what I will need to do as I think the code below will be very slow.
The actual code is a bit different because I'm using ADOdb (and ODBC for the other query) but I'll make it work and post my own answer.
This works, however I think it will be very slow as it goes through the second loop every time:
foreach($array as &$animal)
{
foreach($array2 as $animal2)
{
if($animal['id'] === $animal2['id'])
{
$animal = array_merge($animal, $animal2);
break;
}
}
}
foreach ($array as $a)
$new_array[$a['id']]['name'] = $a['name'];
foreach ($array2 as $a)
$new_array[$a['id']]['age'] = $a['age'];
and this is result:
[1] => Array
(
[name] => Cat
[age] => 123
)
[2] => Array
(
[name] => Mouse
[age] => 321
)
<?php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>
With PHP 5.3 you can do this sort of merge with array_replace_recursive()
http://www.php.net/manual/en/function.array-replace-recursive.php
You're resultant array should look like:
Array (
[0] => Array
(
[id] => 2
[name] => Cat
[age] => 321
)
[1] => Array
(
[id] => 1
[name] => Mouse
[age] => 123
)
)
Which is what I think you wanted as a result.
I would rather prefer array_splice over array_merge because of its performance issues, my solution would be:
<?php
array_splice($array1,count($array1),0,$array2);
?>
$new = array();
foreach ($array as $arr) {
$match = false;
foreach ($array2 as $arr2) {
if ($arr['id'] == $arr2['id']) {
$match = true;
$new[] = array_merge($arr, $arr2);
break;
}
}
if ( !$match ) $new[] = $arr;
}

Categories