Sort array based on 2 values - php

I've created a mirrors system were people can vote for links (Work/Broken)
The array looks like this
Array
(
[0] => Array
(
[id] => 1
[link] => link.com/file.zip
[filename] => file.zip
[good] => 10
[broken] => 5
)
[1] => Array
(
[id] => 2
[link] => link.com/file.zip
[filename] => file.zip
[good] => 10
[broken] => 9
)
[2] => Array
(
[id] => 3
[link] => link.com/file.zip
[filename] => file.zip
[good] => 6
[broken] => 0
)
[3] => Array
(
[id] => 4
[link] => link.com/file.zip
[filename] => file.zip
[good] => 0
[broken] => 0
)
[4] => Array
(
[id] => 5
[link] => link.com/file.zip
[filename] => file.zip
[good] => 2
[broken] => 5
)
What I'm trying to do is sorting the links based on this:
the link who have the best score shows on top
I want to calculate the score like this:
score = Good - BAD
If the score is negative, it would show links with no votes, so the results of this system will be:
Array 2,0,1,3,4

Use a custom sort: function.usort. The 'compare' function calculates the difference of 'good' and 'broken' counts as a 'score'. It then compares the 'scores' and returns the appropriate 'indicator' of +1, 0 or -1.
Tested: PHP 5.3.18 Demonstration at viper-7
Code:
// sort the array based on the only the difference between the 'good' and 'broken' scores.
// to force descending sort then reverse the indicator returned by the comparison function.
usort($source, function ($e1, $e2) {
$e1Score = $e1['good'] - $e1['broken'];
$e2Score = $e2['good'] - $e2['broken'];
if ($e1Score < $e2Score) { return +1; }
if ($e1Score > $e2Score) { return -1; }
return 0;
}
);
Test data:
$source = Array(
Array('id' => 1, 'link' => 'link.com/file.zip', 'filename' => 'file.zip', 'good' => 10, 'broken' => 5),
Array('id' => 2, 'link' => 'link.com/file.zip', 'filename' => 'file.zip', 'good' => 10, 'broken' => 9),
Array('id' => 3, 'link' => 'link.com/file.zip', 'filename' => 'file.zip', 'good' => 6, 'broken' => 0),
Array('id' => 4, 'link' => 'link.com/file.zip', 'filename' => 'file.zip', 'good' => 0, 'broken' => 0),
Array('id' => 5, 'link' => 'link.com/file.zip', 'filename' => 'file.zip', 'good' => 2, 'broken' => 5),
);
Sorted Output:
Array
(
[0] => Array
(
[id] => 3
[link] => link.com/file.zip
[filename] => file.zip
[good] => 6
[broken] => 0
)
[1] => Array
(
[id] => 1
[link] => link.com/file.zip
[filename] => file.zip
[good] => 10
[broken] => 5
)
[2] => Array
(
[id] => 2
[link] => link.com/file.zip
[filename] => file.zip
[good] => 10
[broken] => 9
)
[3] => Array
(
[id] => 4
[link] => link.com/file.zip
[filename] => file.zip
[good] => 0
[broken] => 0
)
[4] => Array
(
[id] => 5
[link] => link.com/file.zip
[filename] => file.zip
[good] => 2
[broken] => 5
)
)

Related

Sorting an array by multiple fields

In my backend I have some code handling teams for a round robin group tournament, and in the end teams are returned in an array and contains match results/stats etc.
I have the following array which I want to sort by two fields in the following order: points (desc), round_difference (desc).
The final and correct order would be: TeamOne, TeamThree, TeamTwo.
How would I go on about this with an array in this format? Is it possible at all? I have looked into array_multisort() however my array keys/structure overall is a bit "odd" compared to the other code examples I found here on the page and was very confusing to me.
Hopefully someone can assist me in this.
Array
(
[1] => Array
(
[1] => Array
(
[id] => 1
[group] => 1
[name] => TeamOne
[tag] => One
[matches] => Array
(
[played] => 1
[won] => 0
[ot_won] => 1
[ot_lost] => 0
[lost] => 0
[round_difference] => 3
[points] => 2
)
)
[238] => Array
(
[id] => 238
[group] => 1
[name] => TeamTwo
[tag] => Two
[matches] => Array
(
[played] => 0
[won] => 0
[ot_won] => 0
[ot_lost] => 0
[lost] => 0
[round_difference] => 0
[points] => 0
)
)
[14] => Array
(
[id] => 14
[group] => 1
[name] => TeamThree
[tag] => Three
[matches] => Array
(
[played] => 1
[won] => 0
[ot_won] => 0
[ot_lost] => 1
[lost] => 0
[round_difference] => -3
[points] => 1
)
)
)
Try uasort() instead and compare the keys like so:
uasort($arr[1],function($a,$b){
# If the points are more/less right off the bat, return results
if($a['matches']['points'] < $b['matches']['points'])
return true;
# If they are the same
elseif($a['matches']['points'] == $b['matches']['points'])
# Compare round_difference sort by that
return ($a['matches']['round_difference'] < $b['matches']['round_difference']);
});
So, sorting something like this:
$arr = array(
1 => array(
1 => array(
'id' => 1,
'group' => 1,
'name' => 'TeamOne',
'tag' => 'One',
'matches' => array(
'played' => 1,
'won' => 0,
'ot_won' => 1,
'ot_lost' => 0,
'lost' => 0,
'round_difference' => 3,
'points' => 2
)
),
238 => array
(
'id' => 238,
'group' => 1,
'name' => 'TeamTwo',
'tag' => 'Two',
'matches' => array(
'played' => 0,
'won' => 0,
'ot_won' => 0,
'ot_lost' => 0,
'lost' => 0,
'round_difference' => 0,
'points' => 0,
)
),
14 => array
(
'id' => 14,
'group' => 1,
'name' => 'TeamThree',
'tag' => 'Three',
'matches' => array
(
'played' => 1,
'won' => 0,
'ot_won' => 0,
'ot_lost' => 1,
'lost' => 0,
'round_difference' => '-3',
'points' => 1,
)
),
17 => array
(
'id' => 17,
'group' => 1,
'name' => 'TeamFive',
'tag' => 'Five',
'matches' => array
(
'played' => 1,
'won' => 0,
'ot_won' => 0,
'ot_lost' => 1,
'lost' => 0,
'round_difference' => '-3',
'points' => 2,
)
)
)
);
Gives you:
Array
(
[1] => Array
(
[1] => Array
(
[id] => 1
[group] => 1
[name] => TeamOne
[tag] => One
[matches] => Array
(
[played] => 1
[won] => 0
[ot_won] => 1
[ot_lost] => 0
[lost] => 0
[round_difference] => 3
[points] => 2
)
)
[17] => Array
(
[id] => 17
[group] => 1
[name] => TeamFive
[tag] => Five
[matches] => Array
(
[played] => 1
[won] => 0
[ot_won] => 0
[ot_lost] => 1
[lost] => 0
[round_difference] => -3
[points] => 2
)
)
[14] => Array
(
[id] => 14
[group] => 1
[name] => TeamThree
[tag] => Three
[matches] => Array
(
[played] => 1
[won] => 0
[ot_won] => 0
[ot_lost] => 1
[lost] => 0
[round_difference] => -3
[points] => 1
)
)
[238] => Array
(
[id] => 238
[group] => 1
[name] => TeamTwo
[tag] => Two
[matches] => Array
(
[played] => 0
[won] => 0
[ot_won] => 0
[ot_lost] => 0
[lost] => 0
[round_difference] => 0
[points] => 0
)
)
)
)

PHP: sorting multiple arrays by common value

I have multiple arrays that have a different structure but they all got a column named "round" and "eventnumber". How do I merge them all into one array where they are ordered by an array with the round and then listed by the eventnumber? (I have made the arrays shorter than they really are)
$a =
Array (
[0] => Array ( [id] => 1 [eventid] => 3 [round] => 1 [eventnumber] => 1 )
[1] => Array ( [id] => 2 [eventid] => 3 [round] => 2 [eventnumber] => 11 )
)
$b =
Array (
[0] => Array ( [id] => 1 [eventid] => 7 [round] => 1 [eventnumber] => 5 )
[1] => Array ( [id] => 2 [eventid] => 8 [round] => 1 [eventnumber] => 3 )
[2] => Array ( [id] => 3 [eventid] => 8 [round] => 2 [eventnumber] => 6 )
)
$c =
Array (
[0] => Array ( [id] => 1 [eventid] => 6 [round] => 2 [eventnumber] => 2 )
[1] => Array ( [id] => 2 [eventid] => 5 [round] => 1 [eventnumber] => 4 )
)
Desired Result:
$rounds =
Array (
[0] => Array ( [id] => 1 [eventid] => 3 [round] => 1 [eventnumber] => 1 )
[1] => Array ( [id] => 2 [eventid] => 8 [round] => 1 [eventnumber] => 3 )
[2] => Array ( [id] => 2 [eventid] => 5 [round] => 1 [eventnumber] => 4 )
[3] => Array ( [id] => 1 [eventid] => 7 [round] => 1 [eventnumber] => 5 )
)
Array (
[0] => Array ( [id] => 1 [eventid] => 6 [round] => 2 [eventnumber] => 2 )
[1] => Array ( [id] => 3 [eventid] => 8 [round] => 2 [eventnumber] => 6 )
[2] => Array ( [id] => 2 [eventid] => 3 [round] => 2 [eventnumber] => 11 )
)
I have looked for answers but cant seem to get this to work.
Thanks for taking the time to help :)
I have replaced your arrays to a,b and c to be simpler. I started by merging the arrays and then sorting them with a comparison function:
$a =
Array (
0 => Array ( "id" => 1, "eventid" => 3, "round" => 1, "eventnumber" => 1 ) ,
1 => Array ( "id" => 2, "eventid" => 3, "round" => 2, "eventnumber" => 11 )
);
$b =
Array (
0 => Array ( "id" => 1, "eventid" => 7, "round" => 1, "eventnumber" => 5 ),
1 => Array ( "id" => 2, "eventid" => 8, "round" => 1, "eventnumber" => 3 ),
2 => Array ( "id" => 3, "eventid" => 8, "round" => 2, "eventnumber" => 6 )
);
$c =
Array (
0 => Array ( "id" => 1, "eventid" => 6, "round" => 2, "eventnumber" => 2 ),
1 => Array ( "id" => 2, "eventid" => 5, "round" => 1, "eventnumber" => 4 )
);
$result = Array();
for ($i = 0; $i < 3; ++$i){
if (isset($a[$i])) {
array_push($result, $a[$i]);
}
if (isset($b[$i])) {
array_push($result, $b[$i]);
}
if (isset($c[$i])) {
array_push($result, $c[$i]);
}
}
function custom_sort($x,$y) {
if ($x['round'] == $y['round']){
return $x['eventnumber']>$y['eventnumber'];
}
return $x['round']>$y['round'];
}
usort($result, "custom_sort");
print_r($result);
To create a $rounds array that separates each round in a different array you can do:
$rounds = Array();
foreach($result as $row){
if (!isset($rounds[$row["round"]])){
$rounds[$row["round"]] = Array();
}
array_push($rounds[$row["round"]], $row);
}
print_r($rounds);
This naturally assumes the previous $results array. I didn't join all the code so that its clearer the separating part.

how to make an all arrays (including associative array) to single level of array using php?

Hope you can help me with this. Because I'm trying to reorder them but i need first to make the be at a single level of array. From associative array to single array.
$MY_ASSOC_ARRAY
Array
(
[0] => Array
(
[MAIN_ID] => 1
[ORDER] => 1
[NAME] => Animal
[PARENT_ID] => 0
[childs] => Array
(
[0] => Array
(
[MAIN_ID] => 4
[ORDER] => 4
[NAME] => doggie
[PARENT_ID] => 1
[childs] => Array
(
[0] => Array
(
[MAIN_ID] => 18
[ORDER] => 18
[NAME] => hunting
[PARENT_ID] => 4
[childs] => Array
(
[0] => Array
(
[MAIN_ID] => 21
[ORDER] => 21
[NAME] => setter
[PARENT_ID] => 18
)
[1] => Array
(
[MAIN_ID] => 22
[ORDER] => 22
[NAME] => pointer
[PARENT_ID] => 18
)
)
)
[1] => Array
(
[MAIN_ID] => 19
[ORDER] => 19
[NAME] => companion
[PARENT_ID] => 4
)
)
)
)
)
)
Alright now the array should not be in that multi level (associative) array instead it will look like this:
Array
(
[0] => Array
(
[MAIN_ID] => 1
[ORDER] => 1
[NAME] => Animal
[PARENT_ID] => 0
)
[1] => Array
(
[MAIN_ID] => 4
[ORDER] => 4
[NAME] => doggie
[PARENT_ID] => 1
)
[2] => Array
(
[MAIN_ID] => 18
[ORDER] => 18
[NAME] => hunting
[PARENT_ID] => 4
)
[3] => Array
(
[MAIN_ID] => 21
[ORDER] => 21
[NAME] => setter
[PARENT_ID] => 18
)
[4] => Array
(
[MAIN_ID] => 22
[ORDER] => 22
[NAME] => pointer
[PARENT_ID] => 18
)
[5] => Array
(
[MAIN_ID] => 19
[ORDER] => 19
[NAME] => companion
[PARENT_ID] => 4
)
)
I'm no sure how will that be possible in the most effecient way without using too much memory that will affect the speed with the use of Php Codeigniter. Thanks!
[UPDATE # 1]
here are the code that I have tried but the order is different
foreach($tree as $key => $value) {
$single[] = $value;
}
And this is the output for this failed attemp...
Array
(
[0] => Array
(
[MAIN_ID] => 1
[ORDER] => 1
[NAME] => Animal
[PARENT_ID] => 0
)
[1] => Array
(
[MAIN_ID] => 4
[ORDER] => 4
[NAME] => doggie
[PARENT_ID] => 1
)
[2] => Array
(
[MAIN_ID] => 18
[ORDER] => 18
[NAME] => hunting
[PARENT_ID] => 4
)
[3] => Array
(
[MAIN_ID] => 19
[ORDER] => 19
[NAME] => companion
[PARENT_ID] => 4
)
[4] => Array
(
[MAIN_ID] => 21
[ORDER] => 21
[NAME] => setter
[PARENT_ID] => 18
)
[5] => Array
(
[MAIN_ID] => 22
[ORDER] => 22
[NAME] => pointer
[PARENT_ID] => 18
)
)
The [NAME] => companion should be at the last array not on 4th ([3] => Array)
UPDATE # 2:
Feel bad about the down votes... if this question or problem is not useful on your end
<?php
$array = Array(
0 => Array
(
'MAIN_ID' => 1,
'ORDER' => 1,
'NAME' => 'Animal',
'PARENT_ID' => 0,
'childs' => Array
(
0 => Array
(
'MAIN_ID' => 4,
'ORDER' => 4,
'NAME' => 'doggie',
'PARENT_ID' => 1,
'childs' => Array
(
0 => Array
(
'MAIN_ID' => 18,
'ORDER' => 18,
'NAME' => 'hunting',
'PARENT_ID' => 4,
'childs' => Array
(
0 => Array
(
'MAIN_ID' => 21,
'ORDER' => 21,
'NAME' => 'setter',
'PARENT_ID' => 18,
),
1 => Array
(
'MAIN_ID' => 22,
'ORDER' => 22,
'NAME' => 'pointer',
'PARENT_ID' => 18,
)
)
),
1 => Array
(
'MAIN_ID' => 19,
'ORDER' => 19,
'NAME' => 'companion',
'PARENT_ID' => 4,
)
)
)
)
)
);
$out = [];
$out = generateArray($array, $out);
print_r($out);
function generateArray($in, $out){
foreach($in as $value){
$childs = false;
if(isset($value['childs'])){
$childs = $value['childs'];
unset($value['childs']);
}
$out[] = $value;
if($childs)
$out = generateArray($childs, $out);
}
return $out;
}
?>

Sorting Multidimensional array with multiple value in PHP [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 7 years ago.
I want to sort array by value P if two P are same then sort by PD if two PD is same then sort by PF same as PA.
How i achieve this?
I have Multidimensional array In PHP Like
PHP:
$abc = array(
array('id' => 1,'name' => 'abc','overall' => array('MP' => '2','W'=> '2','L' => '0','D'=> '0','PF' => '2904','PA' => '1932','PD' => '972','P' => '6')),
array('id' => 1,'name' => 'abc','overall' => array('MP' => '2','W'=> '1','L' => '1','D'=> '0','PF' => '2320','PA' => '1974','PD' => '346','P' => '3')),
array('id' => 1,'name' => 'abc','overall' => array('MP' => '2','W'=> '1','L' => '1','D'=> '0','PF' => '1620','PA' => '1824','PD' => '-204','P' => '3')),
array('id' => 1,'name' => 'abc','overall' => array('MP' => '2','W'=> '0','L' => '2','D'=> '0','PF' => '2200','PA' => '2300','PD' => '-100','P' => '0'))
);
HTML :
Array
(
[0] => Array
(
[id] => 1
[name] => abc
[overall] => Array
(
[MP] => 2
[W] => 0
[L] => 2
[D] => 0
[PF] => 2200
[PA] => 2300
[PD] => -100
[P] => 0
)
)
[1] => Array
(
[id] => 1
[name] => abc
[overall] => Array
(
[MP] => 2
[W] => 1
[L] => 1
[D] => 0
[PF] => 2320
[PA] => 1974
[PD] => 346
[P] => 3
)
)
[2] => Array
(
[id] => 1
[name] => abc
[overall] => Array
(
[MP] => 2
[W] => 1
[L] => 1
[D] => 0
[PF] => 1620
[PA] => 1824
[PD] => -204
[P] => 3
)
)
[3] => Array
(
[id] => 1
[name] => abc
[overall] => Array
(
[MP] => 2
[W] => 2
[L] => 0
[D] => 0
[PF] => 2904
[PA] => 1932
[PD] => 972
[P] => 6
)
)
)
Want similar like this.
Array
(
[0] => Array
(
[id] => 1
[name] => abc
[overall] => Array
(
[MP] => 2
[W] => 2
[L] => 0
[D] => 0
[PF] => 2904
[PA] => 1932
[PD] => 972
[P] => 6
)
)
[1] => Array
(
[id] => 1
[name] => abc
[overall] => Array
(
[MP] => 2
[W] => 1
[L] => 1
[D] => 0
[PF] => 2320
[PA] => 1974
[PD] => 346
[P] => 3
)
)
[2] => Array
(
[id] => 1
[name] => abc
[overall] => Array
(
[MP] => 2
[W] => 1
[L] => 1
[D] => 0
[PF] => 1620
[PA] => 1824
[PD] => -204
[P] => 3
)
)
[3] => Array
(
[id] => 1
[name] => abc
[overall] => Array
(
[MP] => 2
[W] => 0
[L] => 2
[D] => 0
[PF] => 2200
[PA] => 2300
[PD] => -100
[P] => 0
)
)
)
I have tried like this.
$memberArray1 = usort($memberArray, function($a, $b) {
return $b['overall']['P'] - $a['overall']['P'];
});
$memberArray1 = usort($memberArray, function($a, $b) {
return $b['overall']['PD'] - $a['overall']['PD'];
});
But the issue is when i sort like P then it works but after when i sort like PD then it sort by PD not like P.
You can use uasort along with rsort as
uasort($abc,function($a,$b){
$c = $a['P'] - $b['P'];
$c .= $a['PD'] - $b['PD'];
$c .= $a['PF'] - $b['PF'];
$c .= $a['PA'] - $b['PA'];
return $c;
});
array_reverse($abc);
print_r($abc);
Demo

compare two arrays with array_diff

i got two multidimensional arrays and i'm trying to subtract all the values from the second array in the first array.
1st array : named $arrayREQ2
Array (
[0] => Array (
[id] => 3
[subject] => asdasd
[from_id] => 3
[to_id] => 5
[time] => 2014-05-11 10:58:33
)
[1] => Array (
[id] => 2
[subject] => trolis
[from_id] => 4
[to_id] => 3
[time] => 2014-05-08 16:09:30
)
[2] => Array (
[id] => 1
[subject] => bandom
[from_id] => 3
[to_id] => 5
[time] => 2014-05-08 11:50:39
)
)
Second : named $arrayREQ1
Array (
[0] => Array (
[id] => 2
[subject] => trolis
[from_id] => 4
[to_id] => 3
[time] => 2014-05-08 16:09:30
)
)
And my expecting result :
Array (
[0] => Array (
[id] => 3
[subject] => asdasd
[from_id] => 3
[to_id] => 5
[time] => 2014-05-11 10:58:33
)
[1] => Array (
[id] => 1
[subject] => bandom
[from_id] => 3
[to_id] => 5
[time] => 2014-05-08 11:50:39
)
)
I tried use array_diff but it doesn't work:
$diffff = array_diff($arrayREQ2, $arrayREQ1);
it returns empty array.
If want, you could just use plain ol' foreach on this. They check if it matches, if yes, unset that particular key. Consider this example:
$arrayREQ1 = array(array('id' => 2, 'subject' => 'trollis', 'from_id' => 4, 'to_id' => 3, 'time' => '2014-05-08 16:09:30'));
$arrayREQ2 = array(
array('id' => 3, 'subject' => 'asdasd', 'from_id' => 3, 'to_id' => 5, 'time' => '2014-05-11 10:58:33'),
array('id' => 2, 'subject' => 'trollis', 'from_id' => 4, 'to_id' => 3, 'time' => '2014-05-08 16:09:30'),
array('id' => 1, 'subject' => 'bandom', 'from_id' => 3, 'to_id' => 5, 'time' => '2014-05-08 11:50:39'),
);
foreach($arrayREQ2 as $key => $value) {
if($arrayREQ1[0] === $value) {
unset($arrayREQ2[$key]);
}
}
print_r($arrayREQ2);
Sample Output:
Array
(
[0] => Array
(
[id] => 3
[subject] => asdasd
[from_id] => 3
[to_id] => 5
[time] => 2014-05-11 10:58:33
)
[2] => Array
(
[id] => 1
[subject] => bandom
[from_id] => 3
[to_id] => 5
[time] => 2014-05-08 11:50:39
)
)

Categories