I have an array that its values are associate arrays. I need sort this array based on keys;
$list = array (
array("post_id"=>"2","date"=>"2015","title"=>"title2"),
array("post_id"=>"4","date"=>"2017","title"=>"title4"),
array("post_id"=>"3","date"=>"2016","title"=>"title3"),
array("post_id"=>"1","date"=>"2014","title"=>"title1")
);
For example sorting this array by post_id which means turn that array to this:
$list = array (
array("post_id"=>"1","date"=>"2014","title"=>"title1"),
array("post_id"=>"2","date"=>"2015","title"=>"title2"),
array("post_id"=>"3","date"=>"2016","title"=>"title3"),
array("post_id"=>"4","date"=>"2017","title"=>"title4")
);
I searched this forum and find this code:
function array_sort($array, $on, $order=SORT_ASC){
$new_array = array();
$sortable_array = array();
if (count($array) > 0) {
foreach ($array as $k => $v) {
if (is_array($v)) {
foreach ($v as $k2 => $v2) {
if ($k2 == $on) {
$sortable_array[$k] = $v2;
}
}
} else {
$sortable_array[$k] = $v;
}
}
switch ($order) {
case SORT_ASC:
asort($sortable_array);
break;
case SORT_DESC:
arsort($sortable_array);
break;
}
foreach ($sortable_array as $k => $v) {
$new_array[$k] = $array[$k];
}
}
return $new_array;}
but I cant understand what is it exactly doing.
the topic link is:
Sort PHP multi-dimensional array based on key?
You're not sorting by key, so the example you found won't work for you. A simple usort will do it;
$list = array (
array("post_id"=>"2","date"=>"2015","title"=>"title2"),
array("post_id"=>"4","date"=>"2017","title"=>"title4"),
array("post_id"=>"3","date"=>"2016","title"=>"title3"),
array("post_id"=>"1","date"=>"2014","title"=>"title1")
);
function sortPosts($a, $b)
{
if ($a['post_id'] == $b['post_id']) {
return 0;
}
return ($a['post_id'] < $b['post_id']) ? -1 : 1;
}
usort($list, "sortPosts");
This passes your $lists array into a function and compares each of its values - you can see we're comparing the ['post_id'] value for each.
As the post_id's are strings in your original array, you may need to typecast these as integers, but see how you go.
I use this function :
function aasort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
return $array;
}
$list = array (
array("post_id"=>"2","date"=>"2015","title"=>"title2"),
array("post_id"=>"4","date"=>"2017","title"=>"title4"),
array("post_id"=>"3","date"=>"2016","title"=>"title3"),
array("post_id"=>"1","date"=>"2014","title"=>"title1")
);
$outputArray = aasort($list,"post_id");
Most elegant usually is to use the usort() function combined with a closure.
Take a look at this simple demonstration:
<?php
$list = [
["post_id"=>"2","date"=>"2015","title"=>"title2"],
["post_id"=>"4","date"=>"2017","title"=>"title4"],
["post_id"=>"3","date"=>"2016","title"=>"title3"],
["post_id"=>"1","date"=>"2014","title"=>"title1"]
];
usort(
$list,
function($a, $b) {
return $a['post_id'] < $b['post_id'];
}
);
print_r($list); // First output, descending order
usort(
$list,
function($a, $b) {
return $a['post_id'] > $b['post_id'];
}
);
print_r($list); // Second output, ascending order
Note the reversed comparison operator in the two calls, < versus >...
The output of that obviously is:
First output, descending order:
Array
(
[0] => Array
(
[post_id] => 4
[date] => 2017
[title] => title4
)
[1] => Array
(
[post_id] => 3
[date] => 2016
[title] => title3
)
[2] => Array
(
[post_id] => 2
[date] => 2015
[title] => title2
)
[3] => Array
(
[post_id] => 1
[date] => 2014
[title] => title1
)
)
Second output, ascending order:
Array
(
[0] => Array
(
[post_id] => 1
[date] => 2014
[title] => title1
)
[1] => Array
(
[post_id] => 2
[date] => 2015
[title] => title2
)
[2] => Array
(
[post_id] => 3
[date] => 2016
[title] => title3
)
[3] => Array
(
[post_id] => 4
[date] => 2017
[title] => title4
)
)
That probably wasn't the best answer to chose from that question. Just extract the column to sort on, and sort that to sort the original:
array_multisort(array_column($list, 'post_id'), SORT_ASC, $list);
You can use following code:
<?php
$list = array (
array("post_id"=>"2","date"=>"2015","title"=>"title2"),
array("post_id"=>"4","date"=>"2017","title"=>"title4"),
array("post_id"=>"3","date"=>"2016","title"=>"title3"),
array("post_id"=>"1","date"=>"2014","title"=>"title1")
);
$sorted = array_orderby($list, 'post_id', SORT_ASC);
echo "<pre>";
print_r($sorted);
function array_orderby()
{
$args = func_get_args();
$data = array_shift($args);
foreach ($args as $n => $field) {
if (is_string($field)) {
$tmp = array();
foreach ($data as $key => $row)
$tmp[$key] = $row[$field];
$args[$n] = $tmp;
}
}
$args[] = &$data;
call_user_func_array('array_multisort', $args);
return array_pop($args);
}
?>
It will produce following output:
Array
(
[0] => Array
(
[post_id] => 1
[date] => 2014
[title] => title1
)
[1] => Array
(
[post_id] => 2
[date] => 2015
[title] => title2
)
[2] => Array
(
[post_id] => 3
[date] => 2016
[title] => title3
)
[3] => Array
(
[post_id] => 4
[date] => 2017
[title] => title4
)
)
The function in
OP question does:
first collects all values via $on from the subarray (first foreach) and binds it to the $sortable_array via original_array key $k. Like $list[0]['post_id']; is collect in: $sortable_array[0];
After all values are collected, the array will be sorted DESC or ASC (see switch) with asort, that keeps the index=>value connection. So $sortable_array looks like: Before [0=>2,1=>4,2=>3,3=>1] After [3=>1,0=>2,2=>3,1=>4]
So now the values are sorted and the index can be used in the next step.
In the last foreach a new array is generated. The index $k from the $sortable_array is used to get the subsarrays from the original_array in the new order.
note: This part if (is_array($v)) makes the function behavior not predictable, because it takes just the $v if $v is not an subarray else it would take data from the subarray!!!
I searched for my related topic, but didn't find a similar issue.
I have an array within an array and I have an array which I define as my ordering array.
[array1] => Array
(
[23456] => Array
(
[id] => 1
[info] => info
)
[78933] => Array
(
[id] => 1
[info] => info
)
)
and so on....
[orderarray] => Array
(
[0] => Array
(
[id] => 78933
)
[1] => Array
(
[id] => 23456
)
)
I would like to reorder array1 keys by the value of orderarray id.
So the first key should be then 78933 and not like in array1 23456.
Does anybody knows how to continue this?
I know to read the keys from array1.
foreach ($array1 as $key)
{
echo $key;
}
foreach ($orderarray as $key)
{
foreach ($key as $id => val)
{
echo $val;
}
}
So how can I merge both foreach together the best way?
Thank you so much!
You can use a custom key-sort function using uksort()
<?php
$array = array(
"23456" => array("id" => 1, "info" => "info"),
"78933" => array("id" => 1, "info" => "info")
);
$orderarray = array(
array("id" => 78933),
array("id" => 23456)
);
function customSort($a, $b) {
global $orderarray;
$_a = 0; $_b = 0;
foreach ($orderarray as $index => $order) {
$oid = intval($order['id']);
if ($oid == intval($a)) $_a = $index;
if ($oid == intval($b)) $_b = $index;
}
if ($_a == $_b) {
return 0;
}
return ($_a < $_b) ? -1 : 1;
}
uksort($array, "customSort");
print_r($array);
?>
How to get the difference of arrays containing data-types?
First array:
Array
(
[0] => Array
(
[ID] => 21323154
[NAME] => Name_2
[PREVIEW_TEXT] => Text_2
)
)
Second array:
Array
(
[0] => Array
(
[ID] => 543547564
[NAME] => Name_1
[PREVIEW_TEXT] => Text_1
)
[1] => Array
(
[ID] => 222213322
[NAME] => Name_2
[PREVIEW_TEXT] => Text_2
)
[2] => Array
(
[ID] => 333876833
[NAME] => Name_3
[PREVIEW_TEXT] => Text_3
)
)
The result should be an array:
Array
(
[0] => Array
(
[ID] => 543547564
[NAME] => Name_1
[PREVIEW_TEXT] => Text_1
)
[1] => Array
(
[ID] => 333876833
[NAME] => Name_3
[PREVIEW_TEXT] => Text_3
)
)
I tried different options, but they all return the result found the difference, i.e. the first array.
I have a different ID
Just try with:
$output = array_udiff($arraySecond, $arrayFirst, function($a, $b){
return strcmp($a['NAME'], $b['NAME']);;
});
Output:
array(2) {
[0] =>
array(3) {
'ID' =>
int(543547564)
'NAME' =>
string(6) "Name_1"
'PREVIEW_TEXT' =>
string(6) "Text_1"
}
[2] =>
array(3) {
'ID' =>
int(333876833)
'NAME' =>
string(6) "Name_3"
'PREVIEW_TEXT' =>
string(6) "Text_3"
}
}
If both arrays are large, array_diff will be very inefficient, because it compares each element of the first array with each element of the second. A faster solution is to split the process into two steps: first, generate a set of keys to remove:
$remove = array();
foreach($firstArray as $item)
$remove[$item['name']] = 1;
and then iterate over the second array and add "good" items to the result:
$result = array();
foreach($secondArray as $item)
if(!isset($remove[$item['name']]))
$result []= $item;
This will give you linear performance, while array_diff is quadratic.
Diff both arrays against the field (column) you want to, give back only those entries then (thanks to keys):
$col = 'NAME';
$diff = array_intersect_key($b, array_diff(array_column($b, $col), array_column($a, $col)));
print_r($diff);
If you prefer to have this less quadratic but linear, you can also solve it via iteration (inspired by georg's answer but using array_column() again):
$filtered = function ($col, $a, $b) {
return iterator_to_array(call_user_func(function () use ($col, $a, $b) {
$coled = array_flip(array_column($a, $col));
foreach ($b as $bk => $bv) if (!isset($coled[$bv[$col]])) yield $bk => $bv;
}));
};
print_r($filtered('NAME', $a, $b));
With $a and $b as outlined, you will get the following result for both examples:
Array
(
[0] => Array
(
[ID] => 543547564
[NAME] => Name_1
[PREVIEW_TEXT] => Text_1
)
[2] => Array
(
[ID] => 333876833
[NAME] => Name_3
[PREVIEW_TEXT] => Text_3
)
)
// 1.) - diff against column, intersect keys
$filtered = function($col, $a, $b) {
return array_intersect_key($b, array_diff(array_column($b, $col), array_column($a, $col)));
};
// 2.) - iterate and take only unset by column
$filtered = function ($col, $a, $b) {
return iterator_to_array(call_user_func(function () use ($col, $a, $b) {
$coled = array_flip(array_column($a, $col));
foreach ($b as $bk => $bv) if (!isset($coled[$bv[$col]])) yield $bk => $bv;
}));
};
// 3.) - array_udiff against column
$filtered = function($col, $a, $b) {
return array_udiff($b, $a, function ($a, $b) use ($col) {
return strcmp($a[$col], $b[$col]);
});
};
Usage:
print_r($filtered('NAME', $a, $b));
Where $a is the array containing the elements to remove from the $b array. So $a is the first array of the question and $b is the second array of the question.
I'm having a problem. I have a multidimensional array, that looks like this:
Array ( [0] =>
Array (
[0] => Testguy2's post.
[1] => testguy2
[2] => 2013-04-03
)
[1] => Array (
[0] => Testguy's post.
[1] => testguy
[2] => 2013-04-07
)
);
I want to sort the posts from the newest date to the oldest date, so it looks like this:
Array ( [1] => Array (
[0] => Testguy's post.
[1] => testguy
[2] => 2013-04-07
)
[0] => Array (
[0] => Testguy2's post.
[1] => testguy2
[2] => 2013-04-03
)
);
How do I sort it?
function cmp($a, $b){
$a = strtotime($a[2]);
$b = strtotime($b[2]);
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
usort($array, "cmp");
Or for >= PHP 7
usort($array, function($a, $b){
return strtotime($a[2]) <=> strtotime($b[2]);
});
You can do it using usort with a Closure :
usort($array, function($a, $b) {
$a = strtotime($a[2]);
$b = strtotime($b[2]);
return (($a == $b) ? (0) : (($a > $b) ? (1) : (-1)));
});
I'm just stepping away from my desk for the day so I can't offer specifics. But here's a good place to get started that includes examples: array_multisort
$dates = array();
foreach($a AS $val){
$dates[] = strtotime($val[2]);
}
array_multisort($dates, SORT_ASC, $a);
Can anyone tell me how to sort an array by key?
I want to sort this array by price.
this is my input array format
Array
(
[0] => Array
(
[house_data] => Array
(
[id] => 532
[max_person] => 8
[max_bedrooms] => 4
)
[image] => uploads/123.jpg
[price] => 1950
)
[1] => Array
(
[house_data] => Array
(
[id] => 531
[max_person] => 8
[max_bedrooms] => 5
)
[image] => uploads/1234.jpg
[price] => 1495
)
}
Try usort (http://php.net/manual/en/function.usort.php)
You should have something like:
function cmp($a, $b)
{
if ($a['price'] == $b['price']) {
return 0;
}
return ($a['price'] < $b['price']) ? -1 : 1;
}
usort($table, "cmp");
For making it one dimensional use serialize($array) function , it goes like this :$a = array() ; //your multidimensional array$b = array(); //output arrayforeach ($a as $key=>$value){ $b[] = serialize($value);}echo $b ;
Use the array_multisort() function for multidimensional array sorting.