如何在PHP中将数组从线性分布排序到正态分布?

时间:2016-12-19 03:43:27

标签: php sorting

认为有一个原始数组:

$array[] = array('name' => 'a', 'code'=>1); 
$array[] = array('name' => 'b', 'code'=>2); 
$array[] = array('name' => 'c', 'code'=>3); 
$array[] = array('name' => 'd', 'code'=>4); 
$array[] = array('name' => 'e', 'code'=>5); 
$array[] = array('name' => 'f', 'code'=>6); 
$array[] = array('name' => 'g', 'code'=>7); 
$array[] = array('name' => 'h', 'code'=>8); 
$array[] = array('name' => 'i', 'code'=>9);

code进行线性排序,以及如何按code将其排序为正态分布:

$array[] = array('name' => 'a', 'code'=>1); 
$array[] = array('name' => 'c', 'code'=>3); 
$array[] = array('name' => 'e', 'code'=>5); 
$array[] = array('name' => 'g', 'code'=>7); 
$array[] = array('name' => 'i', 'code'=>9); 
$array[] = array('name' => 'h', 'code'=>8); 
$array[] = array('name' => 'f', 'code'=>6); 
$array[] = array('name' => 'd', 'code'=>4); 
$array[] = array('name' => 'b', 'code'=>2);

也许usort有帮助?

更新

当我说Normal Distribution时,我的意思是如下图所示,最大数字在中间:

normal distribution

是否有一些 COMMON 方法可以做到吗?也许这次是'正常发布' 以及下次我想要另一条规则进行排序? 是否有像usort这样的方法来处理它?

2 个答案:

答案 0 :(得分:3)

这样做。下面的代码将数组拆分为两个新数组。任何具有偶数的内容都将添加到数组中,并在开头添加新元素。任何带有奇数的东西都会被添加到另一个新数组的末尾。然后你只需合并它们。

$array = [];

$array[] = array('name' => 'a', 'code'=>1);
$array[] = array('name' => 'b', 'code'=>2);
$array[] = array('name' => 'c', 'code'=>3);
$array[] = array('name' => 'd', 'code'=>4);
$array[] = array('name' => 'e', 'code'=>5);
$array[] = array('name' => 'f', 'code'=>6);
$array[] = array('name' => 'g', 'code'=>7);
$array[] = array('name' => 'h', 'code'=>8);
$array[] = array('name' => 'i', 'code'=>9);



$array1 = [];
$array2 = [];


foreach ($array as $item) {
    $element = array_shift($array);

    if ($element['code'] % 2 == 0) {
        array_unshift($array1, $element);
    } else {
        $array2[] = $element;
    }
}

$array = array_merge($array2, $array1);

答案 1 :(得分:1)

可以在 O(n)中构建所需的数组,如下所示:

$r = [];
for ($i = count($array) - 1; $i >= 0; --$i) {
  if ($i % 2) {
    $r []= $array[$i];
  } else {
    array_unshift($r, $array[$i]);
  }
}

代码从末尾迭代数组项。奇数索引下的项目(当$i % 2非零时)被添加到$r的末尾,偶数索引下的项目被添加到数组的开头。

  

code进行线性排序,如何按code

将其排序为正态分布

上面的代码将生成所需的数组,但未按正常分布排序code!要按code true 正态分布中的项目进行排序,您需要按如下方式计算正态分布的probability density

/**
 * @param float $x the value
 * @param float $mean Mean or expectation of the distribution (median)
 * @param float $stddev Standard deviation
 * @return float Probability density of the normal distribution
 */
function dens_normal($x, $mean, $stddev) {
  $z = ($x - $mean) / $stddev;
  return (1 / ($stddev * sqrt(2.0 * pi()))) * exp(-0.5 * $z * $z);
}

// Calculate the mean code value
$mean = 0;
foreach ($array as $e) { $mean += $e['code']; }
$mean /= count($array);
echo "mean = $mean\n";

// Standard deviation for the code value
$stddev = 1;

usort($array, function ($a, $b) use ($mean, $stddev) {
  $da = dens_normal($a['code'], $mean, $stddev);
  $db = dens_normal($b['code'], $mean, $stddev);
  return $da == $db ? 0 : ($da < $db ? -1 : 1);
});


foreach ($array as $e) {
  printf("%s: %d\n", $e['name'], $e['code']);
}

输出

mean = 5
i: 9
a: 1
b: 2
h: 8
c: 3
g: 7
d: 4
f: 6
e: 5

与均值(5)值的差异越大,数组索引越低。换句话说,数组按降序的“接近程度”与平均值(5)排序。