This question already has answers here:
Remove empty array elements
(27 answers)
Closed 9 years ago.
I have an array
Array ( [0] => 0 [1] => [2] => 3 [3] => )
i want to remove null values from this and the result should be like this
Array ( [0] => 0 [1] => 3)
i don't want to remove 0 value from array.
this will do the trick:
array_filter($arr, static function($var){return $var !== null;} );
Code Example: https://3v4l.org/jtQa2
for older versions (php<5.3):
function is_not_null ($var) { return !is_null($var); }
$filtered = array_filter($arr, 'is_not_null');
Code Example: http://3v4l.org/CKrYO
You can use array_filter() which will get rid of the null empty values from the array
print_r(array_filter($arr, 'strlen'));
You can just loop through it.
<?php
foreach ($array as $i=>$row) {
if ($row === null)
unset($array[$i]);
}
CodePad
If you want to reindex the array to remove gaps between keys, you can just use a new array:
<?php
$array2 = array();
foreach ($array as $row) {
if ($row !== null)
$array2[] = $row;
}
$array = $array2;
CodePad
You are in a world of trouble now, because it is not too easy to distinguish null from 0 from false from "" from 0.0. But don't worry, it is solvable:
$result = array_filter( $array, 'strlen' );
Which is horrible by itself, but seems to work.
EDIT:
This is bad advice, because the trick leans on a strange corner case:
strlen(0) will be strlen("0") -> 1, thus true
strlen(NULL) will be strlen("")->0, thus false
strlen("") will be strlen(("")->0, thus false
etc.
The way you should do it is something like this:
$my_array = array(2, "a", null, 2.5, NULL, 0, "", 8);
function is_notnull($v) {
return !is_null($v);
}
print_r(array_filter($my_array, "is_notnull"));
This is well readable.
<?php
$arr = array( 0 => 0, 1=>null, 2=>3, 3=>null);
foreach ($arr as $key=>$val) {
if ($val === null)
unset($arr[$key]);
}
$new_arr = array_values($arr);
print_r($new_arr);
?>
Out put:
Array
(
[0] => 0
[1] => 3
)
simply
$keys=array_keys($yourArray,NULL);
if(!empty($keys))
{
foreach($keys as $key)
{
unset($yourArray[$key]);
}
}
var_dump($yourarray);
Related
I have an associative array like this [this array is combination of two different arrays]:
I combine arrays and via array_combine() function
$products = array_combine($one_array_key,$second_array_values);
$products = array(
"arn1" =>"A",
"arn2" =>"A",
"arn3" =>"A",
"arn4" =>"B",
"arn5" =>"B",
"arn6" =>"B"
);
So As you can see there are two distinct values from array A and B.
I want two arrays consists of it's keys.
Or in other words: Compare values of associative array and matched values's key will be extract to the other array .
So My expected out is:
$A = array("arn1","arn2","arn3");
$B = array("arn4","arn5","arn6");
My code:
$products = array_combine($one_array_key,$second_array_values);
$products_distinct_values = array_count_values($product);
$products_distinct_values_keys = array_keys($products_distinct_values);
foreach ($products as $key => $value)
{
// what should I need write there, to get the x numbers of array(s), containing *key* of the same *value of array*
}
I SUPER would never use this "variable variables" technique in a professional project, but it does satisfy your brief. I will urge you to find the folly in your XY Problem.
Effectively, the snippet below will synchronously iterate over the two related input arrays and create variably-named result arrays to push values into.
Code: (Demo)
$one_array_key = ['A', 'A', 'A', 'B', 'B', 'B'];
$second_array_values = ['arn1', 'arn2', 'arn3', 'arn4', 'arn5', 'arn6'];
foreach ($one_array_key as $index => $value) {
$$value[] = $second_array_values[$index];
}
var_export($A);
echo "\n---\n";
var_export($B);
Output:
array (
0 => 'arn1',
1 => 'arn2',
2 => 'arn3',
)
---
array (
0 => 'arn4',
1 => 'arn5',
2 => 'arn6',
)
It makes much more sense to have a statically named variable containing keys and related subarrays. This way you can call array_keys() on the result, if you wish, to find out which groups were found in the original input.
Code: (Demo)
$result = [];
foreach ($one_array_key as $index => $value) {
$result[$value][] = $second_array_values[$index];
}
var_export($result);
Output:
array (
'A' =>
array (
0 => 'arn1',
1 => 'arn2',
2 => 'arn3',
),
'B' =>
array (
0 => 'arn4',
1 => 'arn5',
2 => 'arn6',
),
)
You can use the following PHP code to do that.
<?php
$products = array("arn1"=>"A", "arn2"=>"A", "arn3"=>"A", "arn4"=>"B", "arn5"=>"B", "arn6"=>"B");
$A = array();
$B = array();
foreach ($products as $key => $value)
{
if ($value == "A")
{
array_push ($A, $key);
}
else if ($value == "B")
{
array_push ($B, $key);
}
}
print_r ($A);
print_r ($B);
?>
Is there a simpler way to get all array keys that has same value, when the value is unknown.
The problem with array_unique is that it returns the unique array and thus it doesn't find unique values.
That is, for example, from this array:
Array (
[a]=>1000
[b]=>1
[c]=>1000
)
I want to get this
Array (
[a]=>1000
[c]=>1000
)
Another way around this is, if I could find the lonely values, and then their keys, and then use array_diff
This is what I've got so far, looks awful:
$a = array( 'a' => 1000, 'b' => 1, 'c' => 1000 );
$b = array_flip( array_count_values( $a ) );
krsort( $b );
$final = array_keys( $a, array_shift( $b ) );
Update
Using Paulo Freites' answer as a code base, I could get it working pretty easily, maintainable and easy on eyes kind of way… by using the filtering as a static class method I can get the duplicate values from an array by just calling ClassName::get_duplicates($array_to_filter)
private static $counts = null;
private static function filter_duplicates ($value) {
return self::$counts[ $value ] > 1;
}
public static function get_duplicates ($array) {
self::$counts = array_count_values( $array );
return array_filter( $array, 'ClassName::filter_duplicates' );
}
Taking advantage of closures for a more straightforward solution:
$array = array('a' => 1000, 'b' => 1, 'c' => 1000);
$counts = array_count_values($array);
$filtered = array_filter($array, function ($value) use ($counts) {
return $counts[$value] > 1;
});
var_dump($filtered);
This gave me the following:
array(2) {
["a"]=>
int(1000)
["c"]=>
int(1000)
}
Demo: https://eval.in/67526
That's all! :)
Update: backward-compatible solution
$array = array('a' => 1000, 'b' => 1, 'c' => 1000);
$counts = array_count_values($array);
$filtered = array_filter($array, create_function('$value',
'global $counts; return $counts[$value] > 1;'));
var_dump($filtered);
Demo: https://eval.in/68255
Your implementation has a few issues.
1) If there are 2 of value 1000 and 2 of another value, the array_flip will lose one of the sets of values.
2) If there are more than two different values, the array_keys will only find the one value that occurs most.
3) If there are no duplicates, you will still bring back one of the values.
Something like this works always and will return all duplicate values:
<?php
//the array
$a = array( 'a' => 1000, 'b' => 1, 'c' => 1000 );
//count of values
$cnt = array_count_values($a);
//a new array
$newArray = array();
//loop over existing array
foreach($a as $k=>$v){
//if the count for this value is more than 1 (meaning value has a duplicate)
if($cnt[$v] > 1){
//add to the new array
$newArray[$k] = $v;
}
}
print_r($newArray);
http://codepad.viper-7.com/fal5Yz
If you want to get the duplicates in an array try this:
array_unique(array_diff_assoc($array1, array_unique($array1)))
I found this from:
http://www.php.net/manual/en/function.array-unique.php#95203
at the moment I cant figure out another solution...
// target array
$your_array = array('a'=>1000, 'b'=>1, 'c'=>1000);
// function to do all the job
function get_duplicate_elements($array) {
$res = array();
$counts = array_count_values($array);
foreach ($counts as $id=>$count) {
if ($count > 1) {
$r = array();
$keys = array_keys($array, $id);
foreach ($keys as $k) $r[$k] = $id;
$res[] = $r;
}
}
return sizeof($res) > 0 ? $res : false;
}
// test it
print_r(get_duplicate_elements($your_array));
output:
Array
(
[0] => Array
(
[a] => 1000
[c] => 1000
)
)
example #2: - when you have different values multiplied
// target array
$your_array = array('a'=>1000, 'b'=>1, 'c'=>1000, 'd'=>500, 'e'=>1);
// output
print_r(get_duplicate_elements($your_array));
output:
Array
(
[0] => Array
(
[a] => 1000
[c] => 1000
)
[1] => Array
(
[b] => 1
[e] => 1
)
)
if function result has been assigned to $res variable $res[0] gets an array of all elements from original array with first value found more than once, $res[1] gets array of elements with another duplicated-value, etc... function returns false if nothing duplicate has been found in argument-array.
Try this
$a = array( 'a' => 1, 'b' => 1000, 'c' => 1000,'d'=>'duplicate','e'=>'duplicate','f'=>'ok','g'=>'ok' );
$b = array_map("unserialize", array_unique(array_map("serialize", $a)));
$c = array_diff_key($a, $b);
$array = array("1"=>"A","2"=>"A","3"=>"A","4"=>"B","5"=>"B","6"=>"B");
$val = array_unique(array_values($array));
foreach ($val As $v){
$dat[$v] = array_keys($array,$v);
}
print_r($dat);
This question already has answers here:
Get min and max value in PHP Array
(9 answers)
Closed 2 years ago.
The Problem
I have a multidimensional array similar to the one below. What I'm trying to achieve is a way to find and retrieve from the array the one with the highest "Total" value, now I know there's a function called max but that doesn't work with a multidimensional array like this.
What I've thought about doing is creating a foreach loop and building a new array with only the totals, then using max to find the max value, which would work, the only issue would then be retrieving the rest of the data which relates to that max value. I'm not sure that's the most efficient way either.
Any ideas?
Array
(
[0] => Array
(
[Key1] => Key1
[Total] => 13
)
[1] => Array
(
[Key2] => Key2
[Total] => 117
)
[2] => Array
(
[Key3] => Key3
[Total] => 39
)
)
Since PHP 5.5 you can use array_column to get an array of values for specific key, and max it.
max(array_column($array, 'Total'))
Just do a simple loop and compare values or use array_reduce. # is an error suppressor; it hides the fact that $a['total'] is not declared before it is accessed on the first iteration. Demo
$data = array_reduce($data, function ($a, $b) {
return #$a['Total'] > $b['Total'] ? $a : $b ;
});
print_r($data);
// Array( [Key2] => Key2 [Total] => 117 )
It could also be written with arrow function syntax which has been avaiable since PHP7.4. Demo
var_export(
array_reduce(
$data,
fn($result, $row) =>
$result['Total'] > $row['Total']
? $result
: $row,
['Key1' => null, 'Total' => PHP_INT_MIN]
)
);
// array ('Key2' => 'Key2', 'Total' => 117,)
It's so basic algorithm.
$max = -9999999; //will hold max val
$found_item = null; //will hold item with max val;
foreach($arr as $k=>$v)
{
if($v['Total']>$max)
{
$max = $v['Total'];
$found_item = $v;
}
}
echo "max value is $max";
print_r($found_item);
Working demo
I know this question is old, but I'm providing the following answer in response to another question that pointed here after being marked as a duplicate. This is another alternative I don't see mentioned in the current answers.
I know there's a function called max but that doesn't work with a multidimensional array like this.
You can get around that with array_column which makes getting the maximum value very easy:
$arr = [['message_id' => 1,
'points' => 3],
['message_id' => 2,
'points' => 2],
['message_id' => 3,
'points' => 2]];
// max value
$max = max(array_column($arr, 'points'));
Getting the associative key is where it gets a little more tricky, considering that you might actually want multiple keys (if $max matches more than one value). You can do this with an anonymous function inside array_map, and use array_filter to remove the null values:
// keys of max value
$keys = array_filter(array_map(function ($arr) use ($max) {
return $arr['points'] == $max ? $arr['message_id'] : null;
}, $arr));
Output:
array(1) {
[0]=>
int(1)
}
If you do end up with multiples keys but are only interested in the first match found, then simply reference $keys[0].
another simple method will be
$max = array_map( function( $arr ) {
global $last;
return (int)( ( $arr["Total"] > $last ) ? $arr["Total"] : $last );
}, $array );
print_r( max( $max ) );
<?php
$myarray = array(
0 => array(
'Key1' => 'Key1',
'Total' => 13,
),
1 => array(
'Key2' => 'Key2',
'Total' => 117,
),
2 => array(
'Key2' => 'Key3',
'Total' => 39,
),
);
$out = array();
foreach ($myarray as $item) {
$out[] = $item['Total'];
}
echo max($out); //117
unset($out, $item);
Can be done using array_walk(array_walk_recursive if needed)
$arr is the array you want to search in
$largestElement = null;
array_walk($arr, function(&$item, $key) use (&$largestElement) {
if (!is_array($largestElement) || $largestElement["Total"] < $item["Total"]) {
$largestElement = $item;
}
});
You can use php usort function:
http://php.net/manual/en/function.usort.php
A pretty illustrative example is given here:
<?php
function cmp($a, $b)
{
return strcmp($a["fruit"], $b["fruit"]);
}
$fruits[0]["fruit"] = "lemons";
$fruits[1]["fruit"] = "apples";
$fruits[2]["fruit"] = "grapes";
usort($fruits, "cmp");
while (list($key, $value) = each($fruits)) {
echo "\$fruits[$key]: " . $value["fruit"] . "\n";
}
?>
So it will sort the max value to the last array index.
Output:
$fruits[0]: apples
$fruits[1]: grapes
$fruits[2]: lemons
This example is given on aforementioned link
array_reduce accepts a 3rd "initial" parameter. Use this to avoid the bad practice of using "#" error suppression :
$data = array_reduce($data, function ($a, $b) {
return $a['Total'] > $b['Total'] ? $a : $b ;
},['Total' => 0]);
print_r($data);
PHP 7.4
$data = array_reduce($data, fn(a,b) => $a['Total'] > $b['Total'] ? $a : $b, ['Total' => 0]);
I would like to merge two arrays containing a list of files plus their revision in brackets.
For example:
First array:
['A[1]', 'B[2]', 'C[2]', 'D[2]']
Second one:
['B[3]', 'C[4]', 'E[4]', 'F[2]', 'G[2]']
Like I said, I would be able to merge both arrays, but overwriting the first one by the data present in the second one where the letter/filenames collide.
I used this regex to only grab filenames (removing the revision number). I don't know if I am correct on this point:
/\[[^\)]+\]/
The result I am looking for would be this,
['A[1]', 'B[3]', 'C[4]', 'D[2]', 'E[4]', 'F[2]', 'G[2]']
I'm using PHP4 at the moment.
something like:
function helper() {
$result = array();
foreach (func_get_args() as $fileList) {
foreach ($fileList as $fileName) {
list($file, $revision) = explode('[', $fileName, 2);
$revision = trim($revision, ']');
$result[$file] = !isset($result[$file]) ? $revision : max($result[$file], $revision);
}
}
foreach ($result as $file => $revision) {
$result[$file] = sprintf('%s[%s]', $file, $revision);
}
return array_values($result);
}
$a = array('A[1]', 'B[2]', 'C[2]', 'D[2]');
$b = array('B[3]', 'C[4]', 'E[4]', 'F[2]', 'G[2]');
print_r(helper($a, $b));
demo: http://codepad.org/wUMMjGXC
One way would be to map both arrays to
filename => filename[revision]
such that
Array
(
[0] => A[1]
[1] => B[2]
[2] => C[2]
[3] => D[2]
)
becomes
Array
(
[A] => A[1]
[B] => B[2]
[C] => C[2]
[D] => D[2]
)
and then use array_merge (which overrides entries with the same key).
Something like:
function map($array) {
$filenames = array_map(function($value) {
return strstr($value, '[', false);
}, $array);
return array_combine($filenames, $array);
}
$result = array_merge(map($array1), map($array2));
If you want to have numeric indexes, you can call array_values on the result. The code above requires PHP 5.3 but it should be easy to make it compatible with earlier versions. The other caveat is that it would only work if filenames are unique in the array.
DEMO (PHP 5.2 version)
Reference: array_map, strstr, array_combine, array_merge
Simply iterate over each array and assign temporary keys while pushing values into the result array. Iterate the arrays in order so that the second array's values overwrite the first array's values. When finished looping, you can discard the temporary/grouping keys by calling array_values().
Code: (Demo)
$a = ['A[1]', 'B[2]', 'C[2]', 'D[2]'];
$b = ['B[3]', 'C[4]', 'E[4]', 'F[2]', 'G[2]'];
$result = [];
foreach ($a as $v) {
$result[strtok($v, '[')] = $v;
}
foreach ($b as $v) {
$result[strtok($v, '[')] = $v;
}
var_export(array_values($result));
Output:
array (
0 => 'A[1]',
1 => 'B[3]',
2 => 'C[4]',
3 => 'D[2]',
4 => 'E[4]',
5 => 'F[2]',
6 => 'G[2]',
)
Because your input arrays are logically unique in their grouping letter, this functional-style snippet will provide the same result as the above script: (Demo)
var_export(
array_values(
array_reduce(
array_merge($a, $b),
function($result, $v) {
$result[strtok($v, '[')] = $v;
return $result;
}
)
)
);
I have values passed c and 3 from $_GET variable, which I want to look up in an array as values and retrieve their keys. How can I search through the array to return accurate keys?
The code below
<?php
$array1 = array(0 => 'a', 1 => 'c', 2 => 'c');
$array2 = array(0 => '3', 1 => '2', 2 => '3');
$key1 = array_search('c', $array1);
$key2 = array_search('3', $array2);
?>
returns
$key1 = 1;
$key2 = 0;
though I am expecting
$key1 = 2;
$key2 = 2;
foreach ($array1 as $key => $value) {
if ($value == 'c' && $array2[$key] == '3') {
echo "The key you are looking for is $key";
break;
}
}
I'm pretty sure there's a saner way to do whatever you're trying to do though.
The function returned exactly as it should have. The first occurrence of value 'c' exists at index 1 in $array1 and the value '3' has its first occurrence at index 0 in $array2
This behavior is documented in the php docs on array_search and it even supplies you with an alternative if you don't like it:
If needle is found in haystack more than once, the first matching key
is returned. To return the keys for all matching values, use
array_keys() with the optional search_value parameter instead.
If you want to find the last key that has that value, you could reverse your array first.
$array1 = array(0 => 'a', 1 => 'c', 2 => 'c');
$array2 = array(0 => '3', 1 => '2', 2 => '3');
$key1 = array_search('c', $array1);
$key2 = array_search('3', $array2);
var_dump($key1,$key2); //output: int(1) int(0)
$key1 = array_search('c', array_reverse($array1, true));
$key2 = array_search('3', array_reverse($array2, true));
var_dump($key1,$key2); //output: int(2) int(2)
Perhaps something like:
<?php
// for specificly 2 arrays
function search_matching($match1, $match2, array $array1, array $array2) {
foreach($array1 as $key1 => $value1) {
// we may want to add $strict = false argument to distinguish between == and === match
// see http://php.net/manual/en/function.array-search.php
if($value1 == $match1 and isset($array2[$key1]) and $array2[$key1] == $match2) {
return $key1;
}
}
return null;
}
// unlimited
function search_matching(array($matches), array $array/*, ...*/) {
if( count($matches) != func_num_args() - 1)
throw new \Exception("Number of values to match must be the same as the number of supplied arrays");
$arrays = func_get_args();
array_shift($arrays); // remove $matches
$array = array_unshift($arrays); // array to be iterated
foreach($array as $key => $value) {
if($value == $matches[0]) {
$matches = true;
foreach($arrays as $keyA => $valueA) {
if(! isset($arrays[$key] or $valueA != $matches[$keyA+1]) {
$matches = false;
break;
}
}
if($matches)
return $key;
}
}
return null;
}
The functions are created with numerical keys in mind.
They could be made cleaner by offloading some functionality to other function, but I wanted to keep it concise and together for the sake of easily seeing how it works