Sort 2-dimensional array by elements of inner arrays - php

I have an Array with 8 arrays inside.
It looks like this:
[[num,...],[num,...],[num,...],[num,...],[num,...],[num,...],[num,...],[num,...]]
Each of this inner arrays has as its first element a number. Now I want to receive the element of the outer array with the biggest number as first element.
How do I do that?
Thank you very much.

You can define any sorting algorithm by using PHP's usort()
usort($array, function($a, $b) {
return $a[0] > $b[0];
});
This will sort your array, in place, such that the first element will have the largest number as it's first element.

It's not necessary (and is much more expensive) to sort the entire array. Something like this would work:
// initially, regard the first element as the largest
$element = $array[0];
$greatest = $array[0][0];
$length = count($array);
// compare the first value of each array against $greatest, swapping $element if it's larger
for($i = 1; $i < $length; $i++) { // N.B. start with second element
if($array[$i][0] > $greatest) {
$element = $array[$i];
}
}
// $element is now the element with the biggest first value

Check out usort : http://php.net/manual/en/function.usort.php
You'll have to write your own comparison function.

Related

Sorting a two dimensions array using second level values

I have a 2 dimensions array and need to sort it according to some of the second dimension values.
I tried using uksort, but it doesn't work:
$arr = array();
$arr[] = array('name'=>'test1', 'age'=>25);
$arr[] = array('name'=>'test2', 'age'=>22);
$arr[] = array('name'=>'test3', 'age'=>23);
$arr[] = array('name'=>'test4', 'age'=>29);
uksort($arr, "cmp");
print_r($arr);
function cmp($a, $b) {
if ($a['age']==$b['age']) return 0;
return ($a['age'] < $b['age']) ? -1 : 1;
}
Can anyone spot what am I doing wrong?
I think you are looking for uasort().
uksort() will order your array by keys, but you want to sort the arrays by their value.
uksort
Sort an array by keys using a user-defined comparison function
Sorting array by keys means that you take value of a key (in your case it is the same string age for all subarrays). And you sort by value.
So usort is enough - fiddle.

Reducing a multi-dimensional array

I have an array that carries a definite number of dimensions so I'm not really looking at something recursive (Unless maybe for maintainability sake in the future). It's a numeric array gotten from the database with each row holding another array. Each of those level 2 arrays contain strings like
var1, var2 , var3
And so on. Note the irregular appearance of commas in the string. So I intend to break the comma delimited string in the third level then log them in the final array but I get an error saying I am supplying an null array. So I want to know why it says the array is null and how I can make it recognise that as a valid array. My code goes below:
function fetch_each($arr) {
$temp = array();
for ($i = 0; $i < count($arr); $i++) {
for ($j = 0; $j < count($arr[$i]); $j++) {
array_reduce(preg_split("/[\s,]+/", $arr[$i][$j]), function($a, $b) {
return array_push($temp, $a, $b);
});
}
}
return $temp;
}
PS: Please don't mark as duplicate. I don't want to copy someone else's code but want to understand why this does not work. Thanks.
You have this problem because $temp is not visible in the function block.
To solve that, you must use the keyword use (variable_name) next to the function definition as in this example :
array_reduce(preg_split("/[\s,]+/", $arr[$i][$j]), function($a, $b) use (&$temp) {
return array_push($temp, $a, $b);
});
Just a remark, $a will contain the result of array_push
Returns:int the new number of elements in the array.
So you can remove it from the array_push() instruction to keep a clean array with only splitted strings

Combine two assosiative array's if (id) value are the same

So I got two associative arrays containing key-value pairs. They share one key name, and I want to add one array to the other if the "name" values are equal.
So if you have these arrays:
$array1 = [name=>"Foo",
date=>array("2016-06-06", "2016-06-05", "2016-06-04"),
(some other key-value pairs)];
$array2 = [name=>"Foo",
date=>array("2016-06-06", "2016-06-05", "2016-06-04"),
download_count=>array(54,23,15),
(some other key-value pairs)];
the result should be something like this:
$newArray = [name=>"Foo",
date=>array("2016-06-06", "2016-06-05", "2016-06-04"),
(the other key-value pairs from $array1),
app=>array(
name=>"Foo",
date=>array("2016-06-06", "2016-06-05", "2016-06-04"),
download_count=>array(54,23,15),
(the other key-value pairs from $array2))]
Right now I try to loop through both of the array's to see where the names of both array's at index $i,$j are the same, and if they are combine the two.
Here is the code I use for that
foreach($array1 as $foo){
foreach($array2 as $bar){
if($foo["name"] == $bar["name"]){
$foo["app"] = $bar;
}
}
}
alternatively I tried with just regular for loops like this:
for($i = 0; $i < count($array1); $i++){
for($j = 0; $j < count($array2); $i++){
if($array1[$i]["name"] == $array2[$j]["name"]){
$array1[$i]["app"] = $array2[$j];
break;
}
}
}
The result from the first example is just $array1 (unchanged), and the result form the alternative example is an infinite loop.
Could someone help figure out how to get the desirable result?
Edit
Got it working, was just a beginners error in this case both for loops increased $i by one instead of the first loop adding one to $i and the other adding ine to $j

Sorting a non-associative, multidimensional array

I found lots of info about sorting associative arrays but little about sorting non-associative ones. My array is structured/populated this way:
$my_array = array();
$my_array[0][0] = 'whatever3';
$my_array[0][1] = 3
$my_array[1][0] = 'whatever2';
$my_array[1][1] = 2
$my_array[2][0] = 'whatever1';
$my_array[2][1] = 1
I want to sort it by the second value to get:
$my_array[0][0] = 'whatever1';
$my_array[0][1] = 1;
$my_array[1][0] = 'whatever2';
$my_array[1][1] = 2;
$my_array[2][0] = 'whatever3';
$my_array[2][1] = 3;
How can this be achieved considering my array isn't associative?
What about:
usort($combined, function ($a, $b) { return $a[1] - $b[1]; });
With usort you provide a custom comparison function that must return:
0, if the elements must be considered equal.
a negative number, if the first element must be considered smaller than the second one.
a positive number, if the first element must be considered greater than the second one.
In this case, we choose to compare the second element of each item of $combined array.

Interleaving multiple arrays into a single array

I need to merge several arrays into a single array. The best way to describe what I'm looking for is "interleaving" the arrays into a single array.
For example take item one from array #1 and append to the final array. Get item one from array #2 and append to the final array. Get item two from array #1 and append...etc.
The final array would look something like this:
array#1.element#1
array#2.element#1
.
.
.
The "kicker" is that the individual arrays can be of various lengths.
Is there a better data structure to use?
for example,
function array_zip_merge() {
$output = array();
// The loop incrementer takes each array out of the loop as it gets emptied by array_shift().
for ($args = func_get_args(); count($args); $args = array_filter($args)) {
// &$arg allows array_shift() to change the original.
foreach ($args as &$arg) {
$output[] = array_shift($arg);
}
}
return $output;
}
// test
$a = range(1, 10);
$b = range('a', 'f');
$c = range('A', 'B');
echo implode('', array_zip_merge($a, $b, $c)); // prints 1aA2bB3c4d5e6f78910
If the arrays only have numeric keys, here's a simple solution:
$longest = max( count($arr1), count($arr2) );
$final = array();
for ( $i = 0; $i < $longest; $i++ )
{
if ( isset( $arr1[$i] ) )
$final[] = $arr1[$i];
if ( isset( $arr2[$i] ) )
$final[] = $arr2[$i];
}
If you have named keys you can use the array_keys function for each array and loop over the array of keys instead.
If you want more than two arrays (or variable number of arrays) then you might be able to use a nested loop (though I think you'd need to have $arr[0] and $arr[1] as the individual arrays).
I would just use array_merge(), but that obviously depends on what exactly you do.
This would append those arrays to each other, while elements would only be replaced when they have the same non-numerical key. And that might not be a problem for you, or it might be possible to be solved because of attribute order, since the contents of the first arrays' elements will be overwritten by the later ones.
If you have n arrays, you could use a SortedList, and use arrayIndex * n + arrayNumber as a sort index.

Categories