【问题标题】:PHP array sort by elementPHP数组按元素排序
【发布时间】:2015-05-09 01:27:16
【问题描述】:

我有一个包含以下公司记录的 php 数组。 创建后 - 我想排列数组值或创建一个新数组,其中列出的所有公司按距离排序(从小到大)。关于如何完成这项工作的任何建议?

谢谢。

<?php
$company_values = array(
    array(
        'entitysymbol' => 'ANF',
        'distance'     => '0.42',
    ),

    array(
        'entitysymbol' => 'MSFT',
        'distance'     => '0.50',
    ),

    array(
        'entitysymbol' => 'GOOG',
        'distance'     => '0.78',
    ),
);

【问题讨论】:

  • 不需要那么多数组。放一些部分,这样任何人都可以在没有长卷轴的情况下得到它。
  • 实际上我为每家公司都有一个数组浮点值,称为“距离”——(参见上面粘贴的数组示例)..我想按距离值排列公司列表(订单按描述)。
  • 忘记 TL;DR,这是 TW;DR。
  • @steveklein 不确定你的意思?

标签: php arrays sorting


【解决方案1】:

试试这个:

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

有关更多信息,请阅读usort 函数。希望我有所帮助:)

【讨论】:

  • 或者在 PHP 7 中只是 usort($company_values, function ($a, $b) { return $a['distance'] &lt;=&gt; $b['distance']; });
【解决方案2】:

这里有一些代码可以满足你的需求:

<?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);

?>

此代码创建一个包含排序值的新数组,如果您不想要新数组,请替换:

$sorted_company_values = sort_array($company_values);

通过

$company_values = sort_array($company_values);

它基本上是通过dichotomy(more here)binary search实现recursiveinsertion sort

【讨论】:

  • PHP 的过度设计的答案,其中所有基本排序都作为核心的一部分呈现,并且数组在技术上默认为 std::vector/std::map。在计算机科学教育过程中展示基本的结构知识很好,但我不确定你的大学是否会乐于看到(并在以后调试)这样的代码作为任何实际项目的一部分。您的回答还表明对 PHP 语法糖的理解较弱,并且看起来像是从 C(或类似的低/中级)语言移植的代码。
  • 感谢您提供的信息,我写答案是为了在编程方面做得更好,您确实说明了一点。我没有说我的答案是正确的或最好的,但至少它是作品。 (顺便说一句,很好,简单的答案)
【解决方案3】:

正确答案:

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
});

我想强调的是,当你处理浮点值时,你不应该像整数一样比较它们。主要是因为任何数字的浮点表示,例如0.1 可以同时存储为0.09999999970.1000000003。为了避免这个问题,你应该引入“epsilon”变量(这里等于0.0001),这样你就可以说“两个浮点数之间的差小于epsilon,所以我们应该将它们视为相等的数字”。

更多信息可以在这里找到:Floating point numbers,请参阅带有“浮点精度”标题的警告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    • 2016-02-01
    相关资源
    最近更新 更多