Sort multidimensional array by keys - fails on duplicates [duplicate] - php

This question already has answers here:
Sort multi-dimensional array by specific key
(6 answers)
Closed 7 years ago.
I have a function sortBy() that I use to sort multidimensional arrays by a particular key. Here is a sample array:
Array
(
[0] => Array
(
[id] => 4
[type] => 1
[game] => 1
[platform] => 0
[TotalPot] => 7550
)
[1] => Array
(
[id] => 5
[type] => 0
[game] => 2
[platform] => 0
[TotalPot] => 7500
)
)
Here is the function
function sortBy($arr, $field='id', $order=1) {
$a = array();
if ( !is_array($arr) )
return false;
foreach($arr as $subArr) {
$a[$subArr[$field]] = $subArr;
}
if ( $order == 1 ) sort($a);
else rsort($a);
return $a;
}
In this case, calling sortBy($array, 'TotalPot'); would work fine, because the two values for TotalPot are different. However, if you run this example and set both TotalPot fields to $7500, it overwrites the first occurrence with the latter.
What would be the best way to make this function allow for two items with the same value but still keep them in relevant order? I thought about adding another character, an A or 1 to the end, but this seems sloppy and not very predictable, so a better course of action would be greatly appreciated.

You can simplify your code and just use usort(), e.g.
function sortArrayByField(array &$arr, $field = "id", $ASC = TRUE) {
usort($arr, function($a, $b)use($field, $ASC){
if($a[$field] == $b[$field])
return 0;
return $a[$field] > $b[$field] ? $ASC : !$ASC;
});
}
Then just call it like this:
sortArrayByField($array, "TotalPot", TRUE);
print_r($array);

The reason they are getting overwritten is because you're creating an array where the index is the value of the totalPot.
If there are duplicates, then you will only have one array element with the totalPot.
Easiest way is just to usort this:
<?php
$array = [
[
"id" => 4,
"type" => 1,
"game" => 1,
"platform" => 0,
"TotalPot" => 7550
], [
"id" => 5,
"type" => 0,
"game" => 2,
"platform" => 0,
"TotalPot" => 7500
]
];
usort($array, function($a, $b) {
return $a['TotalPot'] - $b['TotalPot'];
});
print_r($array);
Output:
Array
(
[0] => Array
(
[id] => 5
[type] => 0
[game] => 2
[platform] => 0
[TotalPot] => 7500
)
[1] => Array
(
[id] => 4
[type] => 1
[game] => 1
[platform] => 0
[TotalPot] => 7550
)
)
You can also make this a function:
function sortBy($arr, $field='id', $order=1) {
usort($arr, function($a, $b) use ($field, $order) {
if ($order == 1)
return $a[$field] - $b[$field];
else
return $b[$field] - $a[$field];
});
}

Related

Defining values to specific indexes of a multidimensional array [duplicate]

This question already has answers here:
How to access and manipulate multi-dimensional array by key names / path?
(10 answers)
Closed 1 year ago.
I'm trying to create a function that will assign new values to a specific indexes in a multidimensional array:
I Have the array that looks like this:
data[i]['checkin'];
data[i]['checkout'];
data[i]['content'][x]['price'];
data[i]['content'][x]['profit'];
data[i]['content'][x]['exchangerate'];
first parameter of my function will get the array, And second parameter will get the indexes that I want to redefine:
For example:
function defineNewValues(&$arr, $keys) {
//logic
}
Call the function:
defineNewValues($myArray, [
'data.*.content.*.price' => 0,
'data.*.content.*.profit => 0,
]);
Im beliving that recursion is the key for my problem ,
But not really know how to solve it.
Thank You.
could something like this be okay?
I only ask you to study this code not to implement it, for the simple reason that in the future you may have the same type of problem.
function setValue($key,$value,&$array){
$find_parts = explode(".", $key);
$find = $find_parts[0]??null;
if ($find!=null){
if ($find == "*"){
array_shift($find_parts);
foreach($array as &$sub_array){
setValue(implode(".",$find_parts),$value,$sub_array);
}
}else{
if (count($find_parts)>1){
if (array_key_exists($find,$array)){
array_shift($find_parts);
setValue(implode(".",$find_parts),$value,$array[$find]);
}
}else{
if (array_key_exists($find,$array)){
$array[$find] = $value;
}
}
}
}
}
function defineNewValues(&$arr, $keys) {
foreach($keys as $key=>$value){
setValue($key,$value,$arr);
}
}
$myArray=[
"data"=>[
"a"=>[
"content"=>[
"aa"=>[
"price" => 3,
"profit" => 2,
"other" => 1
],
"ab"=>[
"price" => 3,
"profit" => 2,
"other" => 2
]
]
],
"b"=>[
"content"=>[
"ba"=>[
"price" => 3,
"profit" => 2,
"other" => 4
],
"bb"=>[
"price" => 3,
"profit" => 2,
"other" => 5
]
]
],
]
];
defineNewValues($myArray, [
"data.*.content.*.price" => 0,
"data.*.content.*.profit" => 0,
]);
print_r($myArray);
/* OUTPUT
Array
(
[data] => Array
(
[a] => Array
(
[content] => Array
(
[aa] => Array
(
[price] => 0
[profit] => 0
[other] => 1
)
[ab] => Array
(
[price] => 0
[profit] => 0
[other] => 2
)
)
)
[b] => Array
(
[content] => Array
(
[ba] => Array
(
[price] => 0
[profit] => 0
[other] => 4
)
[bb] => Array
(
[price] => 0
[profit] => 0
[other] => 5
)
)
)
)
)
*/
Because the keys you want to replace only occur at one level of the data, the solution doesn't really need to take the entire array structure into account. You can just replace every price and profit key.
array_walk_recursive($example, function(&$value, $key) {
if (in_array($key, ['price', 'profit'])) {
$value = 0;
}
});
Based on your comment on the other answer, my opinion on the "correct and professional way" is that we should try to solve the problem in the simplest way possible, because simple solutions are easy to maintain.

Array sorting by key value in php [duplicate]

This question already has answers here:
How to Sort a Multi-dimensional Array by Value
(16 answers)
Closed 2 years ago.
I would like to sort below array based on amount but I don't know how. Anyone help me
Array(
[0] => Array
(
[id] => 1
[amount] => 20
)
[1] => Array
(
[id] => 2
[amount] => 30
)
[2] => Array
(
[id] => 3
[amount] => 10
)
)
Something like
PHP7+
usort($array, function($a, $b){
return $a['amount'] <=> $b['amount'];
});
What is <=> (the 'Spaceship' Operator) in PHP 7?
< PHP 7
usort($array, function($a, $b){
if( $a['amount'] == $b['amount'] )
return 0;
else if($a['amount'] > $b['amount'])
return 1;
else
return -1
});
OR you can just subtract them like everyone else...
usort [1] will do the job using a custom comparator function which indexes into the amount property and performs a standard integer comparison for less than/greater than. Sort descending with $b["amount"] - $a["amount"] if you wish.
$data = [
[
"id" => 1,
"amount" => 20
],
[
"id" => 2,
"amount" => 30,
],
[
"id" => 3,
"amount" => 10
]
];
usort($data, function ($a, $b) {
return $a["amount"] - $b["amount"];
});
print_r($data);
Output:
Array
(
[0] => Array
(
[id] => 3
[amount] => 10
)
[1] => Array
(
[id] => 1
[amount] => 20
)
[2] => Array
(
[id] => 2
[amount] => 30
)
)
Use usort.
E.g
function sortByAmount($x, $y) {
return $x['amount'] - $y['amount'];
}
usort($array, 'sortByAmount');
echo "<pre>"; print_r($array);
Use usort function like this (know more about usort click here):
$array = array(array('id'=>1,'amount'=>20),array('id'=>2,'amount'=>30),array('id'=>3,'amount'=>10));
Create custom function like this:
function sortByAmount($x,$y){
return $x['amount']-$y['amount'];
}
Then use usort function like this:
usort($array,'sortByAmount');
// then print
echo"<pre>"; print_r($array);

PHP - trying to sort an array by a numeric field [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 9 years ago.
I have an array of data comprising a 'customer' and a 'Total'. (example below). It is drawn from two different databases.
I need a way to sort the array, based on the Total field, so that the Largest Total is at the top. But so far every thing I have tried has resulted in it assuming that 5 is larger than 32
[5, 32, 25, 16, 11]
What's the easiest way to achieve this? I tried adding intval() to the strcmp function, but it made no difference?
$arrayName = array();
$arrayName[] = array ('customer' => 'Customer1', 'Total' => 25);
$arrayName[] = array ('customer' => 'Customer2', 'Total' => 16);
$arrayName[] = array ('customer' => 'Customer3', 'Total' => 32);
$arrayName[] = array ('customer' => 'Customer4', 'Total' => 5);
$arrayName[] = array ('customer' => 'Customer5', 'Total' => 11);
print_r($arrayName);
print "</br>";
//Sort the Arrray by Total
function arrSort1($b, $a)
{
return strcmp($a['Total']), $b['Total']);
};
usort($arrayName, "arrSort1");
print_r($arrayName);
You're comparing by string but you really want to compare by numeric value. Try:
function arrSort1($b, $a)
{
if ($a['Total'] > $b['Total']) {
return 1;
} else if ($a['Total'] < $b['Total']) {
return -1;
}
return 0;
}
The sorted array will look like this:
Array
(
[0] => Array
(
[customer] => Customer3
[Total] => 32
)
[1] => Array
(
[customer] => Customer1
[Total] => 25
)
[2] => Array
(
[customer] => Customer2
[Total] => 16
)
[3] => Array
(
[customer] => Customer5
[Total] => 11
)
[4] => Array
(
[customer] => Customer4
[Total] => 5
)
)

compare multi-dimensional arrays and return they keys who's values are different in php from the first array

I have two multi-dimensional array I want to take only those array whose
key values are different from the first array
Here is my two array:
$array1 = Array
(
[0] => Array
(
[id] => 1
[serial] => k-0001
[u_rec_id] => 1
[employer_office] => uouuououou
[job_type] => ouuou
[job_title] => u
[job_appointment_date] => 2013-07-15
[job_duration] => ouu
)
[1] => Array
(
[id] => 2
[serial] => k-0001
[u_rec_id] => 1
[employer_office] => DDC
[job_type] => Manger
[job_title] => Manager
[job_appointment_date] => 2013-07-17
[job_duration] => one year
)
)
and this is my second array
$array2 = Array
(
[0] => Array
(
[id] => 1
[serial] => k-0001
[u_rec_id] => 1
[employer_office] => uouuououou
[job_type] => ouuou
[job_title] => u
[job_appointment_date] => 2013-07-15
[job_duration] => ouu
)
[1] => Array
(
[id] => 2
[serial] => k-0001
[u_rec_id] => 1
[employer_office] => ouo
[job_type] => uououo
[job_title] => udds
[job_appointment_date] => 2013-07-17
[job_duration] => uo
)
);
I tried array_diff and array_diff_assoc it also not worked for me
i get this error
A PHP Error was encountered
Severity: Notice
Message: Array to string conversion
Filename: history/home.php
Line Number: 729
Something like this should get you there, depending on what exactly you want:
$diff = array_udiff($array1, $array2, function (array $a, array $b) {
return (int)array_diff($a, $b);
});
Adjust the comparison function to compare what exactly you want to compare.
http://php.net/array_udiff
foreach, array_unique and possibly array_udiff should help you here.
PHP Manual:
Unique Arrays
Data Comparison
For Each
For a simple array:
$result = array_unique($array);
In your case there's a function from PHP Manual for this:
<?php
function specified_array_unique($array, $value)
{
$count = 0;
foreach($array as $array_key => $array_value)
{
if ( ($count > 0) && ($array_value == $value) )
{
unset($array[$array_key]);
}
if ($array_value == $value) $count++;
}
return array_filter($array);
}
?>
There's been a post that is similar to what you're asking;
Stack Overflow - array_udiff

Trying to mimic hierarchy by sorting array in PHP

I am trying to sort an array the following way in PHP:
array
0 => id:1203
parent_id: 456
1 => id:456
parent_id:1723
2 => id:1723
parent_id:0
to this:
array
0 => id:1723
parent_id:0
1 => id:456
parent_id:1723
2 => id:1203
parent_id:456
I never sorted an array in PHP before. How would you do it?
Thanks
Is this doing what you want ?
$arr = array(
array('id' => 1203, 'parent_id' => 456),
array('id' => 456, 'parent_id' => 1723),
array('id' => 1723, 'parent_id' => 0)
);
function compare($a, $b) {
if ($a['parent_id'] == 0) return -1;
if ($b['parent_id'] == 0) return 1;
if ($a['id'] == $b['parent_id']) return -1;
if ($b['id'] == $a['parent_id']) return 1;
return 0;
}
usort($arr, 'compare');
print_r($arr);
output:
Array
(
[0] => Array
(
[id] => 1723
[parent_id] => 0
)
[1] => Array
(
[id] => 456
[parent_id] => 1723
)
[2] => Array
(
[id] => 1203
[parent_id] => 456
)
)
I dont see whats the criteria you want to use to sort. Anyway, you could use uasort function , in which you pass a custom function as argument, so in that function you can define whatever criteria you want to order your array. That function would receive 2 arguments (the 2 variables to compare), and you could compare both parent_id (or whatever is you want to compare). To learn what your custom function should return, check this out.
By using uasort instead of usort you can keep your array indexes (as you said in your example).

Categories