Find repeating values in multidimensional array - php

I'm trying to find when the array has 2nd dimension values that are the same so I can deal with them.
I've looked at array_unique and other people who are asking a similar question, but they all delete the values instead of returning them.
Say I have an array like this:
array(
[0] => array(
[laps] => 7,
[corrected_time] => 18
),
[1] => array(
[laps] => 6,
[corrected_time] => 18
),
[2] => array(
[laps] => 7,
[corrected_time] => 18.5
)
)
I'd like to have it return: array(0,1) because they both have the same value for corrected time

Here is one approach. First get the values for corrected_time and convert them to strings (because we'll use them in array_count_values, which only works on ints and strings).
$times = array_map('strval', array_column($your_array, 'corrected_time'));
Then find all the values that occur more than once using array_count_values and array_filter.
$repeats = array_filter(array_count_values($times), function($time) {
return $time > 1;
});
After you have this list of repeated times, you can use it to filter your original array to only include items with repeated times.
$multiples = array_filter($your_array, function($item) use ($repeats){
return isset($repeats[(string) $item['corrected_time']]);
});
You can iterate over this, or if you only want the keys, you can get them with
$keys = array_keys($multiples);

Related

Get values of array using as key values of another array

I have an array with some values (numeric values):
$arr1 = [1, 3, 8, 12, 23]
and I have another associative array that a key (which matches to a value of $arr1) correspond to a value. This array may contain also keys that don't match with $arr1.
$arr2 = [1 => "foo", 2 => "foo98", 3 => "foo20", 8 => "foo02", 12 => "foo39", 15 => "foo44", 23 => "foo91", 34 => "foo77"]
I want as return the values of $arr2 specifying as key the values of $arr1:
["foo", "foo20", "foo02", "foo39", "foo91"]
If possible, all this, without loops, using just PHP array native functions (so in an elegant way), or at least with the minimum number of loops possible.
Minimal loop is simple - 1. as:
foreach($arr1 as $k) {
$res[] = $arr2[$k];
}
You can do that with array_walk but I think this simple way is more readable.
If you insist you can do with array_filter + array_values + in_array as:
$res = array_values(array_filter($arr2,
function ($key) use ($arr1) { return in_array($key, $arr1);},
ARRAY_FILTER_USE_KEY
));
You can see this for more about filtering keys
To do it purely with array functions, you could do it as...
print_r(array_intersect_key($arr2, array_flip($arr1) ));
So array_flip() turns the items you want form the array into the keys for $arr1 and then uses array_intersect_key() to match the keys with the main array and this newly created array.
Gives...
Array
(
[1] => foo
[3] => foo20
[8] => foo02
[12] => foo39
[23] => foo91
)
If you don't want the keys - add array_values() around the rest of the calls...
print_r(array_values(array_intersect_key($arr2, array_flip($arr1) )));
to get
Array
(
[0] => foo
[1] => foo20
[2] => foo02
[3] => foo39
[4] => foo91
)
Although as pointed out - sometimes a simple foreach() is just as good and sometimes better.

sorting array based on child array[0] (unix) value

I need an array sorted by Unix timestamp values. I attempted to use both ksort and krsort before realising that occasionally the timestamp values might be the same (and you cannot have duplicate keys in arrays).
Here's an example array I may be faced with:
$array = array(
[
"unix" => 1556547761, // notice the two duplicate unix values
"random" => 4
],
[
"unix" => 1556547761,
"random" => 2
],
[
"unix" => 1556547769,
"random" => 5
],
[
"unix" => 1556547765, // this should be in the 3rd position
"random" => 9
]
);
So what I'm trying to do is sort them all based on each child arrays unix value, however I cannot figure out how to do so. I have tried countless insane ways (including all other sort functions and many, many for loops) to figure it out - but to no avail.
All help is appreciated.
You can use usort which sort your array by given function
Define function as:
function cmpByUnix($a, $b) {
return $a["unix"] - $b["unix"];
}
And use with: usort($array, "cmpByUnix");
Live example: 3v4l
Notice you can also use asort($array); but this will compare also the "random" field and keep the key - if this what you need then look at Mangesh answer
array_multisort() — Sort multiple or multi-dimensional arrays
array_columns() — Return the values from a single column in the input array
You can use array_multisort() and array_column(), then provide your desired sort order (SORT_ASC or SORT_DESC).
array_multisort(array_column($array, "unix"), SORT_ASC, $array);
Explanation:
In array_multisort(), arrays are sorted by the first array given. You can see we are using array_column($array, "unix"), which means that the second parameter is the order of sorting (ascending or descending) and the third parameter is the original array.
This is the result of array_column($array, "unix"):
Array(
[0] => 1556547761
[1] => 1556547761
[2] => 1556547765
[3] => 1556547769
)
This function sorts an array such that array indices maintain their correlation with the array elements they are associated with. This is used mainly when sorting associative arrays where the actual element order is significant.
Note:If two members compare as equal, their relative order in the sorted array is undefined.
Refer : https://www.php.net/manual/en/function.asort.php
asort($array);
echo "<pre>";
print_r($array);
echo "</pre>";
It will give you the output as
Array
(
[1] => Array
(
[unix] => 1556547761
[random] => 2
)
[0] => Array
(
[unix] => 1556547761
[random] => 4
)
[3] => Array
(
[unix] => 1556547765
[random] => 9
)
[2] => Array
(
[unix] => 1556547769
[random] => 5
)
)
You can keep the array key [1],[0],[3],[2]) as it is Or you can keep it as sequential as per your requirement.

php for loop assign variables in array

I have an array (myArray) which looks like
Array(
[0] => Computer
[1] => House
[2] => Phone
)
I'm trying to set each value dynamically to a number for example
$newValues = [
"computer" => 0,
"House" => 1,
"Phone" => 2,
];
I have the below loop
$y = 0;
for ($x = 0; $x < count($myArray); x++){
$values = [
$myArray[$x] = ($y+1)
];
y++;
}
This incorrectly produces
Array(
[0] => 3
)
You can use array_flip($arr).
link
If I good understand, you want to flip values with keys, so try to use array_flip().
If becomes to work with array first try to do some research in PHP Array functions. ;)
use array_flip() which — Exchanges all keys with their associated values in an array
<?php
$a1=array("0"=>"Computer","1"=>"House","2"=>"Phone");
$result=array_flip($a1);
print_r($result);
?>
then output is:
Array
(
[Computer] => 0
[House] => 1
[Phone] => 2
)
for more information
http://php.net/manual/en/function.array-flip.php
Like the others have said, array_flip will work, however, your actual problems in the code you've written are:
You are using the wrong assignment operator for array keys:
$myArray[$x] = ($y+1) should be $myArray[$x] => ($y+1)
However this type of assignment really isn't necessary as the next problems will show:
You are overwriting $values each iteration with a new array.
To append to $values, you could use:
$values[$myArray[$x]] = $y+1;
If you really want 0 as your first value, don't use y+1 in your assignment.

Find min value in multidimensional array and return key

I have read several similar questions on here, such as this, Finding the minimum value's key in an associative array but I think my problem may be unique in that my source array is not strings as keys.
My source array looks like this,
$dealers = array(
array(
[id] => 1526,
[count] => 2
),
array(
[id] => 1518,
[count] => 5
),
array(
[id] => 1511,
[count] => 9
),
array(
[id] => 1410,
[count] => 3
)
);
I need to get the id of the smallest count value.
I have tried the following,
$low_dealer = array_keys($dealers, min($dealers));
But it appears to be returning the index of the lowest id and not count.
My next attempt was combining another function I found to find the min of the specific column,
$low_dealer = array_keys($dealers, min( array_column( $dealers, 'count' ) ));
But that returned nothing.
EDIT: Also must be able to handle multiple mins, if two or more have the same count number, need to get an array of them back so I can rand() it.
Would appreciate any tips here, thank you!
// indexed array: 2, 5, 9, 3
$counts = array_column($dealers, 'count');
// find index of min value
$index = array_search(min($counts), $counts, true);
// $dealers[$index]['id'];
$dealersMin = min(array_column($dealers, 'count'));
$dealersWithMinCount = array_filter($dealers, function ($dealer) {
global $dealersMin;
return ($dealer['count'] == $dealersMin);
});
var_dump($dealersWithMinCount[array_rand($dealersWithMinCount)]['id']);
eval.in demo
Explanation
First we find the lowest value of 'count' in the array and save that to $dealersMin.
Then we need to get all rows in the $dealers array that have a count of $dealersMin and save that in $dealersWithMinCount.
Then just pick a random element of $dealersWithMinCount with array_rand()

Flatten array in PHP by calculating the average number for the same keys

I have an array in PHP that shows an average number per month. Now this array can contain multiple entries for the same month. If that is the case, the numbers have to be summed up and divided by the count of entries per month:
E.g. May = (3.15 + 2.29 + 2.36) / 3 = 2.6
Input:
$result = [
0 => ['April' => 4.36],
1 => ['May' => 3.15],
2 => ['May' => 2.29],
3 => ['May' => 2.36]
];
Output:
$result = [
[0] => ['April' => 4.36],
[1] => ['May' => 2.60]
];
Any idea how this can be done?
Here In the first loop we are iterating over input array to gather values according to month, and in second loop we are using array_walk to loop-over the array to find average. using function array_sum and count
Try this code snippet here
<?php
ini_set('display_errors', 1);
$Array = [
0 => ['April' => 4.36],
1 => ['May' => 3.15],
2 => ['May' => 2.29],
3 => ['May' => 2.36]
];
$result=array();
//Gathering values according to months.
foreach ($Array as $value)
{
$result[key($value)][]=$value[key($value)];//using key function to get the first key of array
}
//using array_sum for finding sum of array.
array_walk($result,function($value,$key) use (&$newResult){
$newResult[] = array($key =>array_sum($value)/count($value));
});
print_r($newResult);
You can use multi-dimensional arrays.
Multi-dimensional arrays are arrays in arrays, how many ever times you wish.
https://www.w3schools.com/php/php_arrays_multi.asp
http://php.net/manual/en/language.types.array.php
So, relating to you code, let's say November has these numbers:
4,3,2 and 1.
You would do this:
$result = array(
"November" => array(4,3,2,1)
)
Then you would find the length of the array, access the multi-dimensional objects by doing this:
$result["November"][0]
(This will output 4)
Then write a foreach script to determine the average. I'll leave that to you.
try this, check the live demo
$array = [];
foreach($result as $v)
{
$array[key($v)][] = current($v);
}
$result = array_map(function($v){return array_sum($v)/count($v);}, $array);

Categories