Sort Multi-dimensional array by value dynamically with PHP - php

This Stackoverflow answer is 95% of the way there: https://stackoverflow.com/a/10484863. I just need to pass another variable into the function which I believe uses closure.
I want to pass the variable sort:
$sort = get_category_name();
into:
function compareByName($a, $b) {
return strcmp($a["name"], $b["name"]);
}
usort($a, 'compareByName');
so its $a[$sort] and not defined by me as $a[key].
My array:
Array(
[0] => Array
(
[id] => 7
[product_type_id] => 2
[category_en] => Prints
[category_es] => Impresiones
[category_ru] => Печати
)
[1] => Array
(
[id] => 8
[product_type_id] => 2
[category_en] => Drawings
[category_es] => Dibujos
[category_ru] => Рисунки
)
[2] => Array
(
[id] => 9
[product_type_id] => 2
[category_en] => Paintings
[category_es] => Pinturas/Cuadros
[category_ru] => Картины
)
)
should allow me to sort the array by the category based on the users language which is set by get_category_name().

Related

Alphabetically sort array of objects based on property value php

I'm struggling to sort my array of objects into alphabetical order by the title key. Getting error that 'title' is undefined.
I want to go from this:
My Array
(
[0] => Array
(
[area] => TACT
[pages] => Array
(
[0] => Array
(
[id] => 1484
[title] => Registry
)
[1] => Array
(
[id] => 1385
[title] => Education
To:
My Array
(
[0] => Array
(
[area] => TACT
[pages] => Array
(
[0] => Array
(
[id] => 1385
[title] => Education
)
[1] => Array
(
[id] => 1484
[title] => Registry
Have tried:
function sort_alpha_title($a, $b) {
return strnatcmp($a['title'], $b['title']);
}
usort($myArray, 'sort_alpha_title');
You should use
function sort_alpha_title($a, $b) {
return strnatcmp($a['title'], $b['title']);
}
usort($myArray[0]['pages'], 'sort_alpha_title');
Because the title property is a child property of the pages property.
$myArray = array(
array(
'area' => 'TACT',
'pages' => array(
array(
'id' => 1484,
'title' => 'Registry'
),
array(
'id' => 1385,
'title' => 'Education'
)
)
)
);
function sort_alpha_title($a, $b)
{
return strnatcmp($a["title"], $b["title"]);
}
usort($myArray[0]['pages'], 'sort_alpha_title');
var_dump($myArray);
Sry for the doubled answer but i cant add a comment because of my reputation.
tomhuckle wrote
thanks! this works. But only for one of my objects in the array. Sorry the description should of said. ive tried putting a for each loop but that's not working. here's what i tried: foreach($myArray as $a) { usort($a['pages'], 'sort_alpha_title'); }
you dont need the foreach-loop (at the end of your comment) because its already "looped" within one call.
best regards

PHP: usort with closure syntax "use()" [duplicate]

This question already has answers here:
Possible to pass a closure to usort in PHP?
(2 answers)
How can I sort arrays and data in PHP?
(14 answers)
Closed 2 years ago.
EDIT: I rewrote my post in order to be clearer and provide a standalone case with real values (no Ajax anymore).
I have 2 arrays that are exactly identical except that one has the same values but cleaned (html, special chars, etc..).
I would like to evaluate the sorting against "arrayClean" but to sort "arrayOriginal" instead (not arrayClean) according to that evaluation.
So, this is what I have:
<?php
$arrayOriginal = array(
array('id' => '100','surface' => '<span>300</span>','whatever' => 'qSDqsd'),
array('id' => '5465','surface' => '100 ch','whatever' => 'ghjkghjk'),
array('id' => '40489','surface' => '<b>1000</b>','whatever' => 'fgsdfg')
);
$arrayClean = array(
array('id' => '100','surface' => '300','whatever' => 'qSDqsd'),
array('id' => '5465','surface' => '100','whatever' => 'ghjkghjk'),
array('id' => '40489','surface' => '1000','whatever' => 'fgsdfg')
);
usort($arrayOriginal, function($a, $b) use (&$arrayClean) {
return $a['surface'] < $b['surface'];
});
echo '<pre>'; print_r($arrayOriginal); echo '</pre>';
?>
here is what I get (which is wrong as the arrayClean doesn't seem to be taken into account for the sorting) :
Array
(
[0] => Array
(
[id] => 100
[surface] => <span>300</span>
[whatever] => qSDqsd
)
[1] => Array
(
[id] => 40489
[surface] => <b>1000</b>
[pwhatever] => fgsdfg
)
[2] => Array
(
[id] => 5465
[surface] => 100 ch
[whatever] => ghjkghjk
)
)
But if I use arrayClean alone, just to check if the sorting script is right:
usort($arrayClean, function($a, $b) {
return $a['surface'] < $b['surface'];
});
echo '<pre>'; print_r($arrayClean); echo '</pre>';
Then the result is what I expect it to be:
Array
(
[0] => Array
(
[id] => 40489
[surface] => 1000
[whatever] => fgsdfg
)
[1] => Array
(
[id] => 100
[surface] => 300
[whatever] => qSDqsd
)
[2] => Array
(
[id] => 5465
[surface] => 100
[whatever] => ghjkghjk
)
)
So it seems that evaluating arrayClean but sorting arrayOriginal accordingly doesn't work. It only evaluates AND sort arrayOriginal.
Do I use "use()" wrong ? Should I use something else ?
Thank you.
Assuming both arrays are sorted by a common factor (i.e. id).
uksort($arrayOriginal, function($a, $b) use ($arrayClean) {
return $arrayClean[$a]['surface'] < $arrayClean[$b]['surface'];
});
Emphasising once more, to make it work, both arrays MUST contain elements in the same order. In your case elements of both arrays MUST come in the following order (by id): 100, 5465, 40489
BUT I'd rather do something like:
usort($arrayOriginal, function($a, $b) {
return yourSurfaceCleanMethod($arrayOriginal['surface']) < yourSurfaceCleanMethod($arrayOriginal['surface']);
});
All depends on your needs, of course, but if you are using $arrayClean only as a reference for sorting original array and you have that yourSurfaceCleanMethod handy, I'd definitely do the above.
I think the arrayClean is not needed if your arrayOriginal should be sorted according to the content of the HTML tags.
strip_tags() can be used for this in your sort function.
usort($arrayOriginal, function($a, $b) {
return strip_tags($b['surface']) <=> strip_tags($a['surface']);
});
Note: Use the spaceship operator <=> to get correct comparison results 1, 0 and -1.
I accepted Nemoden's answer as a courtesy because technically it answered the question according to its scope (the test case as presented). But here is the solution I found that works best for me :
$arrayOriginal = array(
array('id' => '100','surface' => '<span>300</span>','whatever' => 'qSDqsd'),
array('id' => '5465','surface' => '100 ch','whatever' => 'ghjkghjk'),
array('id' => '40489','surface' => '<b>1000</b>','whatever' => 'fgsdfg')
);
$arrayClean = array(
array('id' => '100','surface' => '300','whatever' => 'qSDqsd'),
array('id' => '5465','surface' => '100','whatever' => 'ghjkghjk'),
array('id' => '40489','surface' => '1000','whatever' => 'fgsdfg')
);
$surface = array_column($arrayClean, 'Surface');
array_multisort($surface, SORT_DESC, SORT_REGULAR, $arrayOriginal);
And then I get this output, which is EXACTLY what I want:
Array
(
[0] => Array
(
[id] => 40489
[surface] => <b>1000</b>
[whatever] => fgsdfg
)
[1] => Array
(
[id] => 100
[surface] => <span>300</span>
[whatever] => qSDqsd
)
[2] => Array
(
[id] => 5465
[surface] => 100 ch
[whatever] => ghjkghjk
)
)
The answer of Nemoden was very helpful BUT it gave me this, for whatever reason:
Array
(
[1] => Array
(
[id] => 40489
[surface] => <b>1000</b>
[whatever] => fgsdfg
)
[0] => Array
(
[id] => 100
[surface] => <span>300</span>
[whatever] => qSDqsd
)
[2] => Array
(
[id] => 5465
[surface] => 100 ch
[whatever] => ghjkghjk
)
)
The sub arrays are PRINTED in the right order but the sub arrays indexes weren't changed. So when exporting to javascript "arrayOriginal", it would come back to its initial sorting because the sub arrays would be re-ordered according to their indexes again. At least, that's what I experienced.
Anyway, now the problem is solved and the answers I got here were very helpful.
Thank you.

Sort associative array by level 4 in php

Here is my sample array, I would like to sort this array based on ShipPrice value which is comes on level 4 of this array, how can we do this in PHP ?
Array
(
[0] => Array
(
[ShippingTypes] =>
[SelectedShipName] =>
[SelectedShipId] =>
[SelectedShipPrice] =>
[MethodName] => UPS
[MethodId] => 6
[SelectedDeliveryDays] =>
[PackageCount] => 1
)
[1] => Array
(
[ShippingTypes] => Array
(
[44] => Array
(
[ShipName] => Local pick up
[ShipPrice] => 12
[DeliveryDays] =>
)
)
[SelectedShipName] => Local pick up
[SelectedShipPrice] => 12
[SelectedShipId] => 44
[MethodName] => Quantity Based
[MethodId] => 3
[SelectedDeliveryDays] =>
)
[2] => Array
(
[ShippingTypes] => Array
(
[1] => Array
(
[ShipName] => KP Office
[ShipPrice] => 10
[DeliveryDays] => 0
)
[2] => Array
(
[ShipName] => Sachet
[ShipPrice] => 15
[DeliveryDays] => 5
)
)
[SelectedShipName] => KP Office
[SelectedShipPrice] => 10
[SelectedShipId] => 1
[MethodName] => Local Pickup From Store
[MethodId] => -1
[SelectedDeliveryDays] => 0
)
)
You can do it using usort and the max ShipPrice you get for all shipping types (supposing that you actually want to check against the max):
usort($results, static function(array $a, array $b) {
return price($a) <=> price($b);
});
function price(array $array): int
{
$shippingTypes = (array) $array['ShippingTypes'];
if (empty($shippingTypes)) {
return 0;
}
return max(array_column($shippingTypes, 'ShipPrice'));
}

Compare three different array and arrange them in same order

I tried to arrange three different arrays in the same order, all three arrays as same size but values are not in the same order. How can I arrange them into the same order?
First array:
Array(
[0] => Array( [id] => 1 )
[1] => Array( [id] => 12 )
[2] => Array( [id] => 25 )
[3] => Array( [id] => 54 )
)
Second array:
Array(
[0] => Array( [id] => 24 )
[1] => Array( [id] => 12 )
[2] => Array( [id] => 54 )
[3] => Array( [id] => 1 )
)
Third array:
Array(
[0] => Array( [id] => 54 )
[1] => Array( [id] => 25 )
[2] => Array( [id] => 1 )
[3] => Array( [id] => 12 )
)
Expected final array result:
Array(
[0] => Array( [id] => 1 )
[1] => Array( [id] => 12 )
[2] => Array( [id] => 25 )
[3] => Array( [id] => 54 )
)
All three arrays are arranged like the first array. I tried a lot but it's not working.
As you want the result to be in the order of the first array, try multisort the arrays with the first array
array_multisort($arr2,$arrone);
array_multisort($arr3,$arrone);
To get all arrays arranged in the same way as a given reference array you can use a custom search function for usort.
function orderarrayByReferencearrayIds(array $referencearray, array $arrayToSort) {
// get an array with the id order of the reference array
$idOrder = array_column($referencearray, 'id');
usort($arrayToSort, function (array $a, array $b) use ($idOrder) {
// get the index in reference sort order of each element
$aIndex = array_search($a['id'], $idOrder);
$bIndex = array_search($b['id'], $idOrder);
return $aIndex - $bIndex;
});
return $arrayToSort;
}
This doesn't work for your second array as the id '24' is not present in the reference array.

Construct a Multidimensional Array

I am working in PHP with array iteration.
I have a multidimensional array like this:
Array
(
[1] => stdClass Object
(
[id] => 1
[comments] => Testing the Data
[stream_context_id] => 5
[stream_entity_id] =>
[class_id] => 1
[parent_id] => 0
[learnt_count] =>
[rating_count] =>
[abused_count] =>
[created_by] => 1
[created_datetime] =>
[stream_context] => comments
[name] =>
[upload_path] =>
[uploadby] =>
[upload_time] =>
)
[2] => stdClass Object
(
[id] => 2
[comments] => Testing the Data
[stream_context_id] => 5
[stream_entity_id] =>
[class_id] => 1
[parent_id] => 0
[learnt_count] =>
[rating_count] =>
[abused_count] =>
[created_by] => 1
[created_datetime] =>
[stream_context] => comments
[name] =>
[upload_path] =>
[uploadby] =>
[upload_time] =>
)
)
Here the first index values i.e. 1 and 2 are the ids mentioned in their corresponding arrays.
I want the same multidimensional array with index values a 0 and 1 and so on.. i.e. the usual format of an array.
Don't know if this is what you meant, but maybe...:
$reindexedArray = array_values($yourArray);
If you also want to convert the stdClass objects to arrays, try:
$reindexedAndArrayifiedArray = array_values(array_map(function ($entry) {
return (array)$entry;
}, $yourArray));
Using array_merge() with a blank array - will renumber numeric indexes:
$result = array_merge(Array(), $your_array_here) ;
This does look like a multidimentional array as you have a named array holding objects.
Your array is currently:
$a = array('1'=>Object, '2'=>Object);
Instead of:
$a = array('1'=>array('id'=>'1', 'comment'=>'some comment'), '2'=>array());
$b = array();
foreach($a as $key=>$val){
$b[] = $val;
}

Categories