2

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',
    ),
);
8
  • that much array is not required . put some part so that any one can get it without a long scroll. Commented May 9, 2015 at 1:30
  • stackoverflow.com/questions/838227/… Commented May 9, 2015 at 1:35
  • actually i have a array float value for each company called "distance" -- (see array example i pasted above).. i would like to arrange the list of companies by that value of distance (order by desc). Commented May 9, 2015 at 1:37
  • Forget about TL;DR, this is TW;DR. Commented May 9, 2015 at 1:39
  • @steveklein not sure what you mean? Commented May 9, 2015 at 1:44

3 Answers 3

2

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 :)

Sign up to request clarification or add additional context in comments.

1 Comment

Or simply usort($company_values, function ($a, $b) { return $a['distance'] <=> $b['distance']; }); in PHP 7.
1

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

2 Comments

Overengineered answer for PHP where all basic sorts are presented as a part of core and where arrays are technically std::vector/std::map by default. It's good to show basic structure knowledge during the Computer Science education process, but I'm not sure that your colleges will be happy to see (and debug later) such code as a part of any real project. Your answer also shows weak understanding of PHP syntactic sugar and looks like a ported code from the C (or similar low/mid level) language.
Thank you for the information, I write answers to get better at programming, and you do make a point.I did not say that my answer was the correct one or the best one, but at least it works. (btw, nice, simple answer)
1

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.