Related
I have sorted a multidimensional array on value distance from low to high. This is an example of the output: (the actual output has around 20 or 30 arrays).
Array
(
[0] => Array
(
[id] => 1
[distance] => 5
[sponsor] => 0
)
[1] => Array
(
[id] => 20
[distance] => 8
[sponsor] => 1
)
[2] => Array
(
[id] => 25
[distance] => 10
[sponsor] => 0
)
[3] => Array
(
[id] => 78
[distance] => 25
[sponsor] => 1
)
)
After sorting on distance from low to high, I want to give priority if sponsor = 1. This is the preferred output:
Array
(
[0] => Array
(
[id] => 20
[distance] => 8
[sponsor] => 1
)
[1] => Array
(
[id] => 78
[distance] => 25
[sponsor] => 1
)
[2] => Array
(
[id] => 1
[distance] => 5
[sponsor] => 0
)
[3] => Array
(
[id] => 25
[distance] => 10
[sponsor] => 0
)
)
Sponsor is either 0 or 1. How can I tackle this problem? I was thinking of, before sorting on distance, I should split up the array in 2 arrays based on sponsor (0,1), sort both arrays on distance, and then merge them with sponsor=1 at the top of the new multidimensional array. Is this the way to do it?
Thank you for your input.
This is slightly modified version of what usort suggests. Assuming source array is called $arr:
usort(
$arr, function($a, $b) {
if ( $a['sponsor'] == $b['sponsor'] ) {
if ( $a['distance'] == $b['distance'] ) {
return 0;
}
return $a['distance'] < $b['distance'] ? -1 : 1;
}
return $a['sponsor'] > $b['sponsor'] ? -1 : 1;
}
);
You have to split original array to 2 arrays: 1st has sponsor=1, 2nd has sponsor=0. Then sort them separately and merge.
Somehow like this:
$array1 = array_filter($array, function ($v) { return $v['sponsor'] == 1; });
$array2 = array_filter($array, function ($v) { return $v['sponsor'] == 0; });
function cmp($a, $b) {
return $a['distance'] < $b['distance']? -1 : 1;
}
usort($array1, cmp);
usort($array2, cmp);
$result = array_merge($array1, $array2);
You can use array_multisort() function to achieve what you want:
<?php
$arr = [
['id' => 1, 'distance' => 5, 'sponsor' => 0],
['id' => 20, 'distance' => 8, 'sponsor' => 1],
['id' => 25, 'distance' => 10, 'sponsor' => 0],
['id' => 78, 'distance' => 25, 'sponsor' => 1],
];
$sponsor = array_column($arr, 'sponsor');
$distance = array_column($arr, 'distance');
// rearrange $arr by sponsor DESC and then by distance ASC
array_multisort($sponsor, SORT_DESC, $distance, SORT_ASC, $arr);
print_r($arr);
That would work but if you use a stable sorting algorithm then you can sort first by distance, then by sponsor descending and you will get your desired results.
Try This :
<?php
$ar = array(
array("10", 11, 100, 100, "a"),
array( 1, 2, "2", 3, 1)
);
array_multisort($ar[0], SORT_ASC, SORT_STRING,
$ar[1], SORT_NUMERIC, SORT_DESC);
var_dump($ar);
?>
or
<?php
$ar1 = array(10, 100, 100, 0);
$ar2 = array(1, 3, 2, 4);
array_multisort($ar1, $ar2);
var_dump($ar1);
var_dump($ar2);
?>
What I'm trying to do is sort a multi-dimensional array that contains decimal values. From what I've tested, floats are having trouble being ordered properly.
Array
(
[0] => Array
(
[company] => Ebay
[weight] => 4.6
)
[1] => Array
(
[company] => Ebay
[weight] => 1.7
)
[2] => Array
(
[company] => Ebay
[weight] => 3.7
)
)
usort($array, 'order_by_weight');
// Sorts DESC highest first
function order_by_weight($a, $b) {
return $b['weight'] - $a['weight'];
}
What is the best way to sort these numbers in descending?
$arr = array(
array('company' => 'A', 'weight' => 4.6),
array('company' => 'B', 'weight' => 1.7),
array('company' => 'C', 'weight' => 3.7),
);
usort($arr, 'order_by_weight');
function order_by_weight($a, $b) {
return $b['weight'] > $a['weight'] ? 1 : -1;
}
var_dump($arr);
PS: it's not a rocket science - this exact "trick" is used as the first example at http://php.net/usort
You can do this with anonymous function in just one line
$arr = array(
array('company' => 'A', 'weight' => 4.6),
array('company' => 'B', 'weight' => 1.7),
array('company' => 'C', 'weight' => 3.7),
);
usort($arr, function($a, $b) { return $b['weight'] > $a['weight'] ;});
print_r($arr);
Hope this helps :)
You can sort the array using array_multisort, altough, this is often used to sort on multiple array values instead of one.
echo "<pre>";
$a = array(
array('company' => 'ebay', 'weight' => 4.6),
array('company' => 'ebay', 'weight' => 1.7),
array('company' => 'ebay', 'weight' => 3.7),
array('company' => 'ebay', 'weight' => 2.7),
array('company' => 'ebay', 'weight' => 9.7),
array('company' => 'ebay', 'weight' => 0.7),
);
$company = array();
$weight = array();
foreach($a as $key=>$val) {
array_push($company, $val['company']);
array_push($weight, $val['weight']);
}
array_multisort($weight, SORT_ASC, $a);
print_r($a);
In case someone wants a more concise code, especially to handle equals condition you will add if condition before #zerkms's solution
using ceil will round fractions up and will sort the decimal numbers correctly
usort($data, function($a, $b)
{
return ceil($a[$_GET['sortby']] - $b[$_GET['sortby']]);
});
As sorting algo here is good example for sort multi dimension array without using any more inbuilt php function
$multiarr = array('0'=>array(
"hashtag" => "a7e87329b5eab8578f4f1098a152d6f4",
"title" => "Flower",
"order" => 3),
'1' => array(
'hashtag' => "b24ce0cd392a5b0b8dedc66c25213594",
"title" => "Free",
"order" => 2),
'2' => array('hashtag' => 'e7d31fc0602fb2ede144d18cdffd816b',
'title' => 'Ready',
'order' => 1
));
sorting function :
function multisort(&$array, $key) {
$valsort = array();
$ret = array();
reset($array);
foreach ($array as $ii => $va) {
$valsort[$ii] = $va[$key];
}
asort($valsort);
foreach ($valsort as $ii => $va) {
$ret[$ii] = $array[$ii];
}
$array = $ret;
}
multisort($multiarr, "order");
: output :
Array
(
[2] => Array
(
[hashtag] => e7d31fc0602fb2ede144d18cdffd816b
[title] => Ready
[order] => 1
)
[1] => Array
(
[hashtag] => b24ce0cd392a5b0b8dedc66c25213594
[title] => Free
[order] => 2
)
[0] => Array
(
[hashtag] => a7e87329b5eab8578f4f1098a152d6f4
[title] => Flower
[order] => 3
)
)
None of the earlier posted answers are demonstrating the most modern syntaxes for sorting by a column value.
If using usort(), use the three-way comparison operator ("spaceship operator ") from PHP7 and if you are on PHP7.4 or higher enjoy the brevity of "arrow function" syntax. For descending directional sorting write $b on the left of the operator and $a on the right. (Demo)
usort($arr, fn($a, $b) => $b['weight'] <=> $a['weight']);
array_multisort() can also be used, but it requires an additional loop to isolate a column of data. (Demo)
array_multisort(array_column($arr, 'weight'), SORT_DESC, $arr);
i got an array like this with unsorted outer index.
$a = array(
(1) => array(1, 2, 3, 0, 5, 4),
(0) => array(2, 1, 5, 0, 3, 4)
);
echo "<br/>Before Sorting: ";
print_r($a);
foreach($a as $b)
array_multisort($b, SORT_ASC, SORT_NUMERIC);
echo "<br/>After Sorting: ";
print_r($a);
which gives me output as below
Before Sorting:
Array
(
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 0
[4] => 5
[5] => 4
)
[0] => Array
(
[0] => 2
[1] => 1
[2] => 5
[3] => 0
[4] => 3
[5] => 4
)
)
After Sorting:
Array
(
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 0
[4] => 5
[5] => 4
)
[0] => Array
(
[0] => 2
[1] => 1
[2] => 5
[3] => 0
[4] => 3
[5] => 4
)
)
AND WHAT I WANT IS
$a = array(
(0) => array(2, 1, 5, 0, 3, 4),
(1) => array(1, 2, 3, 0, 5, 4)
);
please tell me how to deal with.........
How about just using ksort (as you need to reorder your array by key)?
$a = array(
1 => array(1, 2, 3, 0, 5, 4),
0 => array(2, 1, 5, 0, 3, 4)
);
echo "<br/>Before Sorting: ";
print_r($a);
ksort($a);
echo "<br/>After Sorting: ";
print_r($a);
Since you're only wanting to sort by the top level indices, you don't need to use multisort. You don't even need a loop.
Try this:
$a = array(
(1) => array(1, 2, 3, 0, 5, 4),
(0) => array(2, 1, 5, 0, 3, 4)
);
ksort($a);
print_r($a);
Should give you what you want.
See http://www.php.net/manual/en/function.ksort.php for more info.
I have two arrays, I want to merge these two arrays into single array. Please view the detail below:
First Array:
Array
(
[0] => Array
(
[a] => 1
[b] => 2
[c] => 3
)
[1] => Array
(
[a] => 3
[b] => 2
[c] => 1
)
)
Second Array:
Array
(
[0] => Array
(
[d] => 4
[e] => 5
[f] => 6
)
[1] => Array
(
[d] => 6
[e] => 5
[f] => 4
)
)
I want this result. Does somebody know how to do this?
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[1] => Array
(
[0] => 3
[1] => 2
[2] => 1
)
[2] => Array
(
[0] => 4
[1] => 5
[2] => 6
)
[3] => Array
(
[0] => 6
[1] => 5
[2] => 4
)
)
Hope you have understand the question.
Thank you in advance.
Try array_merge:
$result = array_merge($array1, $array2);
FIXED (again)
function array_merge_to_indexed () {
$result = array();
foreach (func_get_args() as $arg) {
foreach ($arg as $innerArr) {
$result[] = array_values($innerArr);
}
}
return $result;
}
Accepts an unlimited number of input arrays, merges all sub arrays into one container as indexed arrays, and returns the result.
EDIT 03/2014: Improved readability and efficiency
more simple and modern way is:
$merged = $array1 + ['apple' => 10, 'orange' => 20] + ['cherry' => 12, 'grape' => 32];
new array syntax from php 5.4
If you want to return the exact result you specify in your question then something like this will work
function array_merge_no_keys() {
$result = array();
$arrays = func_get_args();
foreach( $arrays as $array ) {
if( is_array( $array ) ) {
foreach( $array as $subArray ) {
$result[] = array_values( $subArray );
}
}
}
return $result;
}
As a purely native function solution, merge the arrays, then reindex each subarray.
Code: (Demo)
$a = [
['a' => 1, 'b' => 2, 'c' => 3],
['a' => 3, 'b' => 2, 'c' => 1],
];
$b = [
['d' => 4, 'e' => 5, 'f' => 6],
['d' => 6, 'e' => 5, 'f' => 4],
];
var_export(
array_map('array_values' array_merge($a, $b))
);
Output:
array (
0 =>
array (
0 => 1,
1 => 2,
2 => 3,
),
1 =>
array (
0 => 3,
1 => 2,
2 => 1,
),
2 =>
array (
0 => 4,
1 => 5,
2 => 6,
),
3 =>
array (
0 => 6,
1 => 5,
2 => 4,
),
)
I would like to be able to sort this array by the element array's size;
array(
[0] => array( [0] => 'B', [1] => 'C');
[1] => array( [0] => 'B');
[2] => array( [0] => 'A', [1] => 'C');
[3] => array( [0] => 'A', [1] => 'B', [2] => 'C');
[4] => array( [0] => 'C');
[5] => array( [0] => 'A');
[6] => array( [0] => 'A', [1] => 'B');
)
array(
[0] => array( [0] => 'A');
[1] => array( [0] => 'B');
[2] => array( [0] => 'C');
[3] => array( [0] => 'A', [1] => 'B');
[4] => array( [0] => 'A', [1] => 'C');
[5] => array( [0] => 'B', [1] => 'C');
[6] => array( [0] => 'A', [1] => 'B', [2] => 'C');
)
Using closures (PHP 5.3):
usort($array, function($a, $b) { return count($a) - count($b); });
Without using closures (PHP 5.2):
usort($array, create_function('$a, $b', 'return count($a) - count($b)'));
Note that $array will be sorted in place. Don't look for it in the return value of usort().
I have not tested this, but I hope you can get the point.
function yoursort($a,$b) {
if(!(is_array($a) && is_array($b)) return 0; // item of array is not an array
$cntA = sizeof($a);
$cntB = sizeof($b);
if($cntA!=$cntB) return $cntA-$cntB; // smaller array up
foreach($a as $key=>$val) {
$ordA = ord($a[$key]);
$ordB = ord($b[$key]);
if($ordA!=$ordB) return $ordA-$ordB; // sort sub array by alphabet
}
return 0; // items are equal
}
usort($yourarray,"yoursourt");
Here you can find more about usort
http://php.net/manual/en/function.usort.php
You can do this in 2 steps.
In step 1, sort individual arrays on
value.
In step 2, sort the 2D array, first
based on size and if the size are not
equal sort on the values.
Code:
foreach($input as $key => $val) {
sort($input[$key]);
}
usort($input, "cmp");
print_r($input);
function cmp($a,$b) {
if(count($a) != count($b)) {
return count($a) - count($b);
}
for($i=0;$i<count($a);$i++) {
if($a[$i] != $b[$i]) {
return strcmp($a[$i],$b[$i]);
}
}
return 0;
}
Code in Action