How to remove null values in multi-dimensional array? - php

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.

Related

Reduce Multidimensional Array Into One Array

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
)

counting occurence on multiple PHP array [duplicate]

This question already has answers here:
Count specific values in multidimensional array
(4 answers)
Closed 9 years ago.
I'm looking for a way to count occurence on an array of array.
This is my array :
Array
(
[0] => Array
(
[id] => 671
[title] => BIEND
[img] =>
[ville] => marseille
)
[1] => Array
(
[id] => 670
[title] => BIENC
[img] =>
[ville] => avignon
)
[2] => Array
(
[id] => 669
[title] => BIENB
[img] =>
[ville] => avignon
)
)
And what I would like to have :
Array
(
[avignon] => 2
[marseille] => 1
)
I tried with array_count_values, but it dont seems to be the good way.
Any idea?
You could just go through it manually:
$result = array();
foreach($input as $item)
{
$result[$item['ville']]++;
}
or, slightly nicer perhaps,
$result = array();
foreach($input as $item)
{
$city = $item['ville'];
if(!array_key_exists($city, $result)) {
$result[$city] = 1;
} else {
$result[$city]++;
}
}
Alternatively, you could do some array_map magic to first get an array with all the cities, and then use array_count_values as you planned:
$cities = array_count_values( array_map( function($a) { return $a['ville']; } ) );
Note, I haven't tested this last solution, I personally think the first one expresses the intention better. If you would like to use this one because it is shorter (i.e. less readable) I'll leave it to you to debug and comment it
You can use array_reduce():
$data = Array
(
0 => Array
(
'id' => 671,
'title' => 'BIEND',
'img' => '',
'ville' => 'marseille'
)
,
1 => Array
(
'id' => 670,
'title' => 'BIENC',
'img' => '',
'ville' => 'avignon'
)
,
2 => Array
(
'id' => 669,
'title' => 'BIENB',
'img' => '',
'ville' => 'avignon'
)
);
$result = array_reduce($data, function(&$cur, $x)
{
$cur[$x['ville']] = isset($cur[$x['ville']])?$cur[$x['ville']]+1:1;
return $cur;
}, []);
$my_array = array(...);
$result = array();
foreach ($my_array as $arr) {
$key = $arr['ville'];
if (! array_key_exists($key, $result){
$result[$key] = 1;
continue;
}
$result[$key] += 1;
}
I would write something like this. Array and subArray should be renamed according to their content.
$villes = array();
foreach($yourArray as $subArray) {
if(!in_array($subArray['ville'], $villes)) {
$villes[$subArray['ville']] = 1;
} else {
$villes[$subArray['ville']]++;
}
}
var_dump($villes);

remove duplicates from array (array unic by key) [duplicate]

This question already has answers here:
Filter/Remove rows where column value is found more than once in a multidimensional array
(4 answers)
Closed 3 months ago.
Array
(
[0] => Array
(
[file] => /var/websites/example.com/assets/images/200px/1419050406e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
[md5] => 42479bee7a304d2318250de2ef1962a9
[url] => http://example.com/assets/images/200px/1419050406e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
)
[1] => Array
(
[file] => /var/websites/example.com/assets/images/200px/21277792606e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
[md5] => 42479bee7a304d2318250de2ef1962a9
[url] => http://example.com/assets/images/200px/21277792606e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
)
)
How can I remove md5 key duplicates from above array?
<?php
$data = array(
array(
'md5' => 'alpha',
'some' => 'value',
),
array(
'md5' => 'alpha',
'some' => 'other value',
),
array(
'md5' => 'bravo',
'some' => 'third value',
),
);
// walk input array
$_data = array();
foreach ($data as $v) {
if (isset($_data[$v['md5']])) {
// found duplicate
continue;
}
// remember unique item
$_data[$v['md5']] = $v;
}
// if you need a zero-based array, otheriwse work with $_data
$data = array_values($_data);
PHP does already have a function to remove duplicate elements from an array. But unfortunately, array_unique does only support string based comparisons:
Note: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same. The first element will be used.
The problem is that any array turned into a string is equal to any other array:
Arrays are always converted to the string "Array"; […]
But you can use the uniqueness of array keys to solve this:
$index = array();
foreach ($arr as $key => $item) {
if (isset($index[$item['md5']])) {
unset($item[$key]);
}
$index[$item['md5']] = TRUE;
}
Here is my final function after your help guys.... Hope it helps somebody in the future...
$data = array(
array(
'md5' => 'alpha',
'some' => 'value',
),
array(
'md5' => 'alpha',
'some' => 'other value',
),
array(
'md5' => 'bravo',
'some' => 'third value',
),
);
// walk input array
function remove_duplicateKeys($key,$data){
$_data = array();
foreach ($data as $v) {
if (isset($_data[$v[$key]])) {
// found duplicate
continue;
}
// remember unique item
$_data[$v[$key]] = $v;
}
// if you need a zero-based array
// otherwise work with $_data
$data = array_values($_data);
return $data;
}
$my_array = remove_duplicateKeys("md5",$data);
As array_unique operates on flat arrays, you can not use it directly. But you can first map all 'md5' values to a flat array, unique it and then get the elements with array_intersect_key:
$allMd5s = array_map(function($v) {return $v['md5'];}, $array);
$uniqueMd5s = array_unique($md5);
$result = array_intersect_key($arr, $uniqueMd5s);
Use array_filter(). Quick code test (doesn't necessarily mirror your situation, but you should get the idea):
<?php
header('Content-Type: Text/Plain');
$array = array(
0 => array('name' => 'samson'),
1 => array('name' => 'delilah'),
2 => array('name' => 'samson'),
3 => array('name' => 'goliath'),
);
$md5Processed = array();
$newArray = array_filter($array, "uniqueMD5");
print_r($newArray);
exit;
function uniqueMD5( $data ){
global $md5Processed;
if( !in_array( $data['name'], $md5Processed ) )
{
$md5Processed[] = $data['name'];
return true;
}
}
// your array
$array = array(...);
// will be used to store md5 hashes
$md5 = array();
// walk through array
foreach ($array as $key => $arr) {
// have we already seen this md5 hash?
if (in_array($arr['md5'], $md5)){
// remove element
unset($array[$key]);
}else {
// keep element, but add it's md5
$md5[] = $arr['md5'];
}
}
Tldr.: The obligatory one-liner:
$out = array_values ( array_intersect_key( $in, array_unique( array_column( $in, 'md5' ) ) ) );
And step by step (with my own example):
$in = [
[ 'k' => 'a' ],
[ 'k' => 'a' ],
[ 'k' => 'b' ]
];
print_r( array_column( $in, 'k' ) );
array_column returns a flat array, only with the values from all 'k'-keys:
Array
(
[0] => a
[1] => a
[2] => b
)
We can now filter that with array_unique:
print_r( array_unique( array_column( $in, 'k' ) ) ) );
To get:
Array
(
[0] => a
[2] => b
)
See that we kept the keys of the original array (0 and 2)?
We can use that with array_intersect_key. It computes the intersection of arrays using keys for comparison.
print_r( array_intersect_key( $in, array_unique( array_column( $in, 'k' ) ) ) );
We get the first [0] and third [2] entry of our original array.
Array
(
[0] => Array
(
[k] => a
)
[2] => Array
(
[k] => b
)
)
Now the keys are messed up (which might lead to problems if for loops), so we wrap the whole thing in array_values:
print_r(
array_values( array_intersect_key( $in, array_unique( array_column( $in, 'k' ) ) ) )
);
Array
(
[0] => Array
(
[k] => a
)
[1] => Array
(
[k] => b
)
)
Take a look at the function array_unique.

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 );

Categories