Reputation: 601
I have a php array that holds the following company records. Once created - I would like to arrange the array values or create a new array with all the companies listed order by distance (smallest to largest).
<?php
$company_values = array(
array(
'entitysymbol' => 'ANF',
'distance' => '0.42',
),
array(
'entitysymbol' => 'MSFT',
'distance' => '0.50',
),
array(
'entitysymbol' => 'GOOG',
'distance' => '0.78',
),
);
Upvotes: 2
Views: 544
Reputation: 1146
The right answer:
usort($array, function ($a, $b)
{
if (abs($a['distance'] - $b['distance']) <= 0.0001)
{
return 0; # equal
}
return $a['distance'] <=> $b['distance']; # swap $a and $b here for DESC order
});
I would like to highlight that when you deal with float values you should NOT compare them like integers. Mainly because float representation of any number, e.g. 0.1
can be stored as 0.0999999997
or 0.1000000003
in the same time. To avoid this problem you should introduce "epsilon" variable (which is here equals to 0.0001
), so you'll be able to say "the difference between two float numbers is less than epsilon, so we should value them as equal numbers".
More info can be found here: Floating point numbers, refer to warning with a "Floating point precision" title.
Upvotes: 1
Reputation: 43
Give this a try:
function cmp($a, $b) {
if ($a['distance'] == $b['distance']) {
return 0;
}
return ($a['distance'] < $b['distance']) ? -1 : 1;
}
usort($company_values,"cmp");
var_dump($company_values);
For more information, take a read of usort function. Hope I've helped :)
Upvotes: 2
Reputation: 303
Here is some code which will do what you want :
<?php
// Define your array that needs sorting
$company_values = array(
array(
'entitysymbol' => 'MSFT',
'distance' => '0.60',
),
array(
'entitysymbol' => 'ANF',
'distance' => '0.42',
),
array(
'entitysymbol' => 'GOOG',
'distance' => '0.57',
),
array(
'entitysymbol' => 'MSFT',
'distance' => '0.50',
),
array(
'entitysymbol' => 'ANF',
'distance' => '0.30',
),
array(
'entitysymbol' => 'GOOG',
'distance' => '0.78',
),
array(
'entitysymbol' => 'MSFT',
'distance' => '0.50',
),
array(
'entitysymbol' => 'ANF',
'distance' => '0.42',
),
array(
'entitysymbol' => 'GOOG',
'distance' => '0.88',
)
);
// Function to initialise a, b, and c before we start our search
function refresh_dichotomy($array) {
$a = 0;
$b = sizeof($array) - 1;
$c = (int)(($a + $b) / 2);
return [$a, $b, $c];
}
// Recursive dichotomy function to close in on where we need to insert the next element
function get_next_indexes($a, $b, $c, $array, $key, $value) {
// If the value stored in the middle element is higher
if($array[$c][$key] > $value) {
// We lower the value of b
$b = $c;
// Otherwise
} else {
// We increse the value of a
$a = $c;
}
// If a and b are not adjacent
if($b - $a > 1) {
// Get the middle value
$c = (int)(($a + $b) / 2);
// And dig deeper
$a = get_next_indexes($a, $b, $c, $array, $key, $value);
}
return $a;
}
// Function to Fill the new array with the sorted values of the old one
function sort_array($old_array) {
// Add the first element
$new_array = Array($old_array[0]);
// Cycle through the remaining elements
for($i = 1; $i < sizeof($old_array); $i++) {
// First check if the next element is smaller than the smallest value
if($old_array[$i]['distance'] < $new_array[0]['distance']) {
// If it is, then put it in first place
array_splice($new_array, 0, 0, Array($old_array[$i]));
}
// Or if the next element is bigger than the biggest value
else if($old_array[$i]['distance'] > $new_array[count($new_array) - 1]['distance']) {
// If it is, then put it in last place
array_splice($new_array, count($new_array), 0, Array($old_array[$i]));
// Otherwise, find where we need to insert the next element
} else {
// Create 3 variables that will help us search via dichotomy
$a;
$b;
$c;
// Initialise their values to fit the current size of the new array
$init = refresh_dichotomy($new_array);
$a = $init[0];
$b = $init[1];
$c = $init[2];
// Find where we need to insert our next value
$a = get_next_indexes($a, $b, $c, $new_array, 'distance', $old_array[$i]['distance']);
// Insert our new element
array_splice($new_array, $a+1, 0, Array($old_array[$i]));
}
}
return $new_array;
}
// Create an array to store the sorted values
$sorted_company_values = array();
// Sort !
$sorted_company_values = sort_array($company_values);
// Preview before and after
print_r($company_values);
echo("<br><br>");
print_r($sorted_company_values);
?>
This code creates a new array containing your sorted values, if you don't want a new array, replace :
$sorted_company_values = sort_array($company_values);
by
$company_values = sort_array($company_values);
It's basicly an implementation of a recursive insertion sort via dichotomy (more here) or binary search
Upvotes: 1