This question already has answers here:
How to Sort a Multi-dimensional Array by Value
(16 answers)
How can I sort arrays and data in PHP?
(14 answers)
Closed 8 years ago.
I've got an multidimensional array which is build like this:
array(
array(
'zahlungen_id' => 1,
'reise_id' => 1,
'name' => 'Liam Schnell',
'schul_id' => 1,
'summe' => 49,
'art' => 'PayPal',
'sicher' => 0,
'datum' => '2014-05-05'
),
array(
'zahlungen_id' => 2,
'reise_id' => 3,
'name' => 'Max Göllner',
'schul_id' => 1,
'summe' => 49,
'art' => 'SOFORT',
'sicher' => 1,
'datum' => '2014-05-06'
),
array(
'zahlungen_id' => 3,
'reise_id' => 2,
'name' => 'Sasha Novalja',
'schul_id' => 2,
'summe' => 49,
'art' => 'Kreditkarte',
'sicher' => 1,
'datum' => '2014-05-05'
),
array(
'zahlungen_id' => 4,
'reise_id' => 1,
'name' => 'Hans Wurst',
'schul_id' => 1,
'summe' => 49,
'art' => 'Sofort',
'sicher' => 0,
'datum' => '2014-05-04'
)
);
Is there any way I can use 'schul_id' to sort the array itself? Like a descending schul_id?
array_multisort covers this, here's a sample from their docs tweaked to your question:
foreach($data as $key => $row) {
$schul_id[$key] = $row['schul_id'];
}
array_multisort($schul_id, SORT_DESC, $data);
print_r($data);
First comment was right! I used this one
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;
}
You are looking for uasort:
function cmp($a, $b) {
if ($a["schul_id"] == $b["schul_id"]) {
return 0;
}
return ($a["schul_id"] > $b["schul_id"]) ? -1 : 1;
}
uasort($array, 'cmp');
Related
I'd like to re-index a multidimensional array to be like this:
[
0 => ['id' => 1, 'children' => [['id' => 2], ['id' => 3]]],
4 => ['id' => 5, 'children' => [['id' => 6], ['id' => 7]]]
8 => ...
]
If I use array_walk_recursive I get:
[
0 => ['id' => 1, 'children' => [['id' => 2], ['id' => 3]]],
1 => ['id' => 4, 'children' => [['id' => 5], ['id' => 6]]]
2 => ...
]
This is almost there, but not quite...
array_walk_recursive($out, function(&$item, $key) {
if($key == 'id')
{
$item = $this->_i;
$this->_i++;
}
});
Managed to solve this, it not pretty (I later found that the problem was elsewhere and left the code in an proof of concept state). Posting this if anyone else need this kind of structure.
// restructure the array for reindexing
$out = [];
$k = 0;
foreach ($arr as $as)
{
$test = ['id' => $k, 'items' => $as];
array_push($out, $test);
$k++;
}
// reindex multidimensiona array
$i = 1;
array_walk_recursive($out, function(&$item, $key) {
global $i;
if($key == 'id')
{
$item = $i;
$i++;
}
});
// final array restructuring
$res = [];
foreach($out as $oo)
{
$firstKey = array_key_first($oo);
$res[$oo[$firstKey]] = $oo['items'];
}
var_dump( $res );
Lets assume I have a soccer league array:
$array = [
'teamId1' =>
[
'games' => 7,
'wins' => 2,
'loss' => 4,
'duals' => 1,
'point' => 7
],
'teamId2' =>
[
'games' => 7,
'wins' => 3,
'loss' => 1,
'duals' => 3,
'point' => 12
],
'teamId3' =>
[
'games' => 7,
'wins' => 4,
'loss' => 3,
'duals' => 0,
'point' => 12
],
'teamId4' =>
[
'games' => 7,
'wins' => 6,
'loss' => 0,
'duals' => 1,
'point' => 19
],
'teamId5' =>
[
'games' => 7,
'wins' => 3,
'loss' => 2,
'duals' => 2,
'point' => 11
],
.
.
.
'teamId18' =>
[
'games' => 7,
'wins' => 5,
'loss' => 0,
'duals' => 2,
'point' => 17
],
];
and I want to sort this By POINT DESC; so I did use this function to sort my array by point:
function sortArray($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;
}
$sortByPoint = sortArray($result, 'point', SORT_DESC);
Ok, now I have an array sorted by point, but now I need something like fine tune my array to reorder array in which when two-or more- teams have same point, the team/s with more wins come before other.
I know I can loop through sorted array and do something, but I'm sure there's shorter and tricky way to do that.
Does anyone any idea about that?
Thanks in Advance
It would be easier to write a specific sort for this. Using usort(), you can add layers of complexity to the conditions as you need it in a simple function...
usort($array, function ($a, $b) {
if ( $a['point'] == $b['point'] ){
// Sort by wins (descending)
return $b['wins'] - $a['wins'];
}
// Sort by points descending
return $b['point'] - $a['point'] ;
});
print_r($array);
This sorts the actual array, so output $array.
You could expand it further by saying if the same number of wins, sort by losses etc.
My multidimensional arrays are
$input_array = array(
array(
'First' => 1,
'Third' => 3
),
'Second' => 2,
'Fourth' => 4
);
$another_array = array(
'First' => array(
'Third' => 3,
'Fifth' => 5
),
'Second' => 2,
'Fourth' => 4
);
How can I change the key case of these two multidimensional arrays using array_change_key_case() in PHP?
Find answer here http://php.net/manual/en/function.array-change-key-case.php#114914
function array_change_key_case_recursive($arr)
{
return array_map(function($item){
if(is_array($item))
$item = array_change_key_case_recursive($item);
return $item;
},array_change_key_case($arr));
}
$input_array = array(array('First'=>1,'Third'=>3),'Second'=>2,'Fourth'=>4);
return array_change_key_case_recursive($input_array);
Try demo https://implode.io/LCW5CG
I have this initial array:
[
0 => ['id' => 5, 'value' => 50],
1 => ['id' => 6, 'value' => 60],
2 => ['id' => 7, 'value' => 70],
]
and want to convert it to:
[
5 => ['value' => 50],
6 => ['value' => 60],
7 => ['value' => 70],
]
At first, I tried to use map, but it can't modify the array keys, so I thought reduce would solve the problem because it reduces the array to a single value, in this case, an array. So I tried:
array_reduce(
$array,
function($carry, $item) {
return $carry[$item['id']] = $item['value'];
},
[]
);
But it returns this error Cannot use a scalar value as an array. What am I doing wrong? Does array_reduce cannot receive an array as an initial value?
Your array_reduce didn't work because You weren't returning the accumulator array (carry in Your case) from the callback function.
array_reduce(
$array,
function($carry, $item) {
$carry[$item['id']] = $item['value'];
return $carry; // this is the only line I added :)
},
[]
);
I came to this question while looking for a way to use array_reduce, so I felt I should write this comment. I hope this will help future readers. :)
As Mark Bakerdid it. I also did with foreach loop.
$arr = array(
array('id' => 5, 'value' => 50),
array('id' => 6, 'value' => 60),
array('id' => 7, 'value' => 70)
);
$result = array();
$result = array_column($arr, 'value', 'id');
array_walk($result, function(&$value) { $value = ['value' => $value]; });
//I did this using foreach loop, But the OP need it through array function.
//foreach($arr as $key => $value){
// $result[$value['id']] = array('value' => $value['value']);
//}
echo '<pre>';
print_r($result);
Result:
Array
(
[5] => Array
(
[value] => 50
)
[6] => Array
(
[value] => 60
)
[7] => Array
(
[value] => 70
)
)
Sometimes the best solutions are the simplest. Loop through your array and assign the id and value to a new array.
$new_array = array();
foreach ($array as $key => $arr) {
$new_array[$arr['id']] = array('value' => $arr['value']);
}
You can do it functionally. I suspect it's not actually more readable however.
array_combine(
array_column($a, 'id'),
array_map(function($v) { return ['value' => $v['value']]; }, $a)
);
Or even...
array_map(
function($v) { return ['value' => $v['value']]; },
array_column($a, null, 'id')
)
array_reduce($ar, function ($acc, $item) {
$acc[$item['id']] = [ 'value' => $item['value']];
return $acc;
}, [])
I want to combine two arrays like this:
1st array:
array( "ATTENDED" => 1,
"TENTATIVE" => 2, //
"REJECTED" => 3,
"OUTSTANDING" => 4,
"ACCEPTED" => 6
);
2nd Array:
array ( 1 => 29,
4 => 30,
6 => 47
);
I want to get the results like this:
array ( 'ATTENDED' => 29,
'OUTSTANDING' => 30,
'ACCEPTED' => 47
);
2nd array is flexible. I can flip keys and values.
or better yet:
array( "ATTENDED" => 29,
"TENTATIVE" => 0, //
"REJECTED" => 0,
"OUTSTANDING" => 30,
"ACCEPTED" => 47
);
I know there must be a simple solution.
Any ideas?
foreach ($arr1 as $k1 => $v1) {
$arr1[$k1] = isset($arr2[$v1]) ? $arr2[$v1] : 0;
}
edit-
This is without an explicit loop, although I don't think this is really better, but maybe cooler though.
$mapped = array_map(function($valFromArr1) use ($arr2) {
return isset($arr2[$valFromArr1]) ? $arr2[$valFromArr1] : 0;
}, $arr1);
I can't think of a sane way to just use pure php functions.
$labels = array(
"ATTENDED" => 1,
"TENTATIVE" => 2,
"REJECTED" => 3,
"OUTSTANDING" => 4,
"ACCEPTED" => 6
);
$values = array(
1 => 29,
4 => 30,
6 => 47
);
$results = array();
foreach ($labels as $label => $id) {
$results[$label] = array_key_exists($id, $values) ? $values[$id] : 0;
}