PHP - Sorting a multidimensional array - php

Array
(
[data] => Array
(
[0] => Array
(
[name] => Nicki Escudero
[id] => 27700035
)
[1] => Array
(
[name] => Yorgo Nestoridis
[id] => 504571368
)
)
)
How can I sort this multidimensional array using its name?
I tried with array_multisort but it's not working.

If you want to use array_multisort, you would use the following:
$array = array(
'data' => array(
array(
'name' => 'Yorgo Nestoridis',
'id' => 504571368,
),
array(
'name' => 'Nicki Escudero',
'id' => 27700035,
),
),
);
$names = array();
foreach($array['data'] as $datum) {
$names[] = $datum['name'];
}
array_multisort($names, SORT_ASC, $array['data']);
var_dump($array); // now sorted by name
The other choice is to use a custom comparison function:
function compareNames($a, $b) {
return strcmp($a['name'], $b['name']);
}
usort($array['data'], 'compareNames');

It is already sorted :-) What do you want to sort by? And where is the data coming from? if you get it from a DB you should sort differently.

If those are the only two values you have, you can try making id the index of the array and the name can be the value. You can then use asort to sort the array by name and maintain the index-value relation.
By making id the index, I mean $array[27700035] would return Nicki Escudero.
// Copy the array to a new array.
foreach($array as $val) {
$newArray[$val['id']] = $val['name'];
}
asort($newArray);
Edit: I've gone through the manual and you can also use usort with a custom comparison function. Although I've never used this and can be of very little help... PHP usort

Related

Sort PHP foreach() loop in Cakephp

I'm slowly learning PHP, and I need some help with sorting through a foreach() loop. Currently, this loop grabs an ID and Name from a database table and displays it in a list, however, I'm having problems sorting that list in alphabetical order. This is what is looks like now where all the records are retrieved and presented in a neat list:
<?php foreach ($disabilities as $disability):?>
<option value=<?=($disability->id)?>><?=($disability->name)?></option>
<?php endforeach; ?>
And this is what I have tried:
<?php myArray = array($disabilities)
sort($disabilities)
foreach ($disabilities as $disability): ?>
<option value=<?=($disability->id)?>><?=($disability->name)?></option>
<?php endforeach; ?>
Any tips on whether I'm on the right/wrong path would be greatly appreciated!
you can achieve this by two ways.
1) sort this while querying from the database.
2) sort arrays in php, here is an example code for sorting in php.
//stdclass object arrays to simple array
$disabilities = json_decode(json_encode($object), True);
$sortArray = array();
foreach($disabilities as $disability){
foreach($disability as $key=>$value){
if(!isset($sortArray[$key])){
$sortArray[$key] = array();
}
$sortArray[$key][] = $value;
}
}
$orderby = "name"; //change this to whatever key you want to apply sorting for
array_multisort($sortArray[$orderby], SORT_ASC, $disabilities);
hope it works for you
Edit: As I have changed it from stdClass Object to array now you will echo like this
echo $disability['name'];
You can use PHP usort function add user defined comparison function.
$obj = (object) array(
['id' => '1', 'name' => 'Ronda'],
['id' => '2', 'name' => 'Aba'],
['id' => '3', 'name' => 'Mac']
);
//convert obj to array usort only accept array
$disabilities = json_decode(json_encode($obj), true);
//define custom function
function sortByName($a, $b) {
//compare two strings
return strcmp($a['name'], $b['name']);
}
//sort using usort before use
usort($disabilities, 'sortByName');
//output
Array ( [0] => Array ( [id] => 2 [name] => Aba ) [1] => Array ( [id] => 3 [name] => Mac ) [2] => Array ( [id] => 1 [name] => Ronda ) )
Working demo: https://repl.it/repls/GruesomeExaltedDevicedriver, After sort the array you can directly use in your foreach.

Spliting .txt file lines in to multi-layered array key value pairs then sorting it

Since this question has a long explanation, I'll ask the question, then have the explanation below -- Can you sort a multidimensional array by their internal array key value, or is there a better way to get around sorting key value pairs that will have inevitable duplicates, than just using an array?
I am mostly unfamiliar with using PHP and want to learn how to store data.
The very simple example I made is just two HTML form inputs for a score and a name and a PHP file to handle the input to be stored in a plain .txt file, which was originally written with the pattern
42|John
32|Jane
25|John
I was able to successfully split the data, sort it, add the new inputted values then store it all back in the text file to be displayed somewhere else, using the name as the key and the score as the value.
I did all this only to realize that it would only store sort and display the last value associated with each name (i.e.)
42|John
32|Jane
25|John
would be sorted to
32|Jane
25|John
because you, obviously, can't have two of the same keys in an array, which is something I completely overlooked.
My solution, currently is to have an extra number that is unique to each name/score pair, which I formatted in the text file as
1|42|John
2|32|Jane
3|25|John
I then split them into a multidimensional array using this foreach loop
foreach($arr as $key => $value) {
$lineData = explode("|", $value);
$scores[$lineData[0]] = array($lineData[1] => $lineData[2]);
}
To get this output
Array
(
[1] => Array
(
[42] => John
)
[2] => Array
(
[32] => Jane
)
[3] => Array
(
[25] => John
)
)
which avoids overwriting any duplicate names or scores, but leaves me in a position where I can't (to my knowledge) use arsort() to sort the array in to highest to lowest.
You can use array_multisort for that, in combination with array_column. Because the key values are strings, you need to also convert them to integers, for which you can use array_map("intval", ...):
foreach($arr as $value) {
$result[] = explode("|", $value);
}
array_multisort(array_map("intval", array_column($result, 0)), $result);
After the above code has run, $result will be sorted by the key values:
[
['25', 'John'],
['32', 'Jane'],
['42', 'John']
]
To reverse the order, apply array_reverse to the result.
Alternative
You could also decide to sort the original array without conversion to a 2D array, and sort it with a custom sort callback, using usort and (again) intval:
usort($arr, function ($a, $b) {
return intval($a) - intval($b);
});
Then $arr will be sorted to:
[
'25|John',
'32|Jane',
'42|John'
]
To reverse the order, switch the position of $a and $b in the sort callback function:
return intval($b) - intval($a);
If we make a small change to your foreach iteration like this:
foreach($arr as $key => $value) {
$lineData = explode("|", $value);
$scores[] = array('score' => $lineData[1], 'name' => $lineData[2]);
}
Your array will have:
Array
(
[0] => Array
(
[score] => 42
[name] => John
)
[1] => Array
(
[score] => 32
[name] => Jane
)
[2] => Array
(
[score] => 25
[name] => John
)
)
You can use the uasort function, which takes the array to sort, and an user-defined function to do the sorting. The code would look like this:
function compare($a, $b)
{
if ($b['score'] == $a['score']) {
if ($a['name'] == $b['name']) {
return 0;
} elseif ($a['name'] < $b['name']) {
return -1;
} else {
return 1;
}
} else {
return ($b['score'] - $a['score']);
}
}
print_r($scores);
uasort($scores, 'compare');
print_r($scores);
Which gives the following result:
Array
(
[1] => Array
(
[score] => 32
[name] => Jane
)
[2] => Array
(
[score] => 25
[name] => John
)
[0] => Array
(
[score] => 42
[name] => John
)
)
When you use a user-defined function for the sorting you need to return one of 3 values (0 of the values as equal, -1 if $a < $b, and 1 if $b > $a. In this case we're sorting first by score (descending), then by name (ascending). Since you need to order from highest to lowest score, the comparison is $b against $a, for ascending order is $a against $b. I didn't consider the extra number necessary. If you need it then change this line:
$scores[] = array('score' => $lineData[1], 'name' => $lineData[2]);
To this:
$scores[$lineData[0]] = array('score' => $lineData[1], 'name' => $lineData[2]);

Fetching a multidimensional array

I am trying to edit a plugin that is fetching a multidimensional array, then breaking it out into a foreach statement and doing stuff with the resulting data.
What I am trying to do is edit the array before it gets to the foreach statement. I want to look and see if there is a key/value combination that exists, and if it does remove that entire subarray, then reform the array and pass it to a new variable.
The current variable
$arrayslides
returns several subarrays that look like something like this (I remove unimportant variables for the sake of briefness):
Array (
[0] => Array (
[slide_active] => 1
)
[1] => Array (
[slide_active] => 0
)
)
What I want to do is look and see if one of these subarrays contains the key slide_active with a value of 0. If it contains a value of zero, I want to dump the whole subarray altogether, then reform the multidimensional array back into the variable
$arrayslides
I have tried a few array functions but have not had any luck. Any suggestions?
$arrayslides = array(0 => array ( 'slide_active' => 1, 'other_data' => "Mark" ),
1 => array ( 'slide_active' => 0, 'other_data' => "ABCDE" ),
2 => array ( 'slide_active' => 1, 'other_data' => "Baker" ),
3 => array ( 'slide_active' => 0, 'other_data' => "FGHIJ" ),
);
$matches = array_filter($arrayslides, function($item) { return $item['slide_active'] == 1; } );
var_dump($matches);
PHP >= 5.3.0
I know its not so efficient but still
foreach ($arraySlides as $key => $value)
{
if(in_array('0', array_values($value))
unset($arraySlides[$key]);
}

Sort 2D Array in PHP

I have an array that looks like this:
Array
(
[90] => Array
(
[1056] => 44.91
[1055] => 53.56
[1054] => 108.88
[1053] => 23.28
),
[63] => Array
(
[1056] => 44.44
[1055] => 53.16
[1054] => 108.05
),
[21] => Array
(
[1056] => 42.83
[1055] => 51.36
[1054] => 108.53
)
);
Both keys ([x] and [y]) refer to IDs in my database, so those need to stay intact. The order of the [x] does not matter, but I need to sort each array by the value of [y].
Edit:
I have tried this loop, but it does not seem to work:
foreach($distance as $key=>$value) {
asort($value,SORT_NUMERIC);
}
Use ksort (or uksort) to sort the arrays by their keys.
UPDATE: Use asort (or uasort) to sort by values, preserving keys.
UPDATE 2: Try this
foreach($distance as &$value) {
asort($value,SORT_NUMERIC);
}
Like this?
array_walk($array, 'asort');
Use asort() for sorting by values. It maintains the index associations.
For the loop, you need to pass $value by reference, so you need to use &$value.
array_multisort($arrindex1, SORT_DESC, $arrindex2, SORT_DESC, $array);

Sorting an Array of Arrays in PHP --> Need a Good Algorithm

I have an array of 15000 elements each of which is an array of 4 elements. I want to sort by the second element of the 4. Originally I made the original array's keys the second element and then k-sorted but unfortunately, some of the second elements are duplicates and since one key can't refer to multiple elements i lost some elements in transition. I could bubble sort by the second element but I'm looking for something that runs at least on the order of nlog(n). Can anyone think of a good algorithm (or possibly a function in php that I don't know about) that can sort by the second element? Thank you!
I think you can use usort and define the cmp_function to use the second element.
As others have stated, usort or uasort to maintain the array keys is what you want:
<?php
$myArray = array(
'fruits' => array(
array('apples', 'oranges', 'bananas')
),
'vegetables' => array(
array('lettuce', 'carrots', 'peas')
),
'monkeys' => array(
array('Curious George', 'Amy', 'Marcel')
)
);
// PHP 5.3+ example using a closure
uasort($myArray, function(array $a, array $b) {
// Use whatever sorting algorithm you like
return strnatcasecmp($a[1], $b[1]);
});
var_export($myArray);
Running the above will output:
array (
'monkeys' =>
array (
0 =>
array (
0 => 'Curious George',
1 => 'Amy',
2 => 'Marcel',
),
),
'vegetables' =>
array (
0 =>
array (
0 => 'lettuce',
1 => 'carrots',
2 => 'peas',
),
),
'fruits' =>
array (
0 =>
array (
0 => 'apples',
1 => 'oranges',
2 => 'bananas',
),
),
)
Here's an example that doesn't use a closure for pre PHP 5.3:
sortFunc(array $a, array $b)
{
return strnatcasecmp($a[1], $b[1]);
}
uasort($myArray, 'sortFunc');
I don't know what the internal implementation of usort is, but I'd bet it's better than bubblesort (it's probably quicksort).

Categories