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

在PHP中如何将数组从线性分布排序到正态分布?,php,sorting,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',

假设有一个原始数组:

$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能帮上忙


更新

当我说正态分布时,我的意思是像下图一样,最大的数字在中间:

是否有一些
常用的
方法可以做到这一点?也许这次是“正态分布”,下次我要另一个排序规则?

是否有类似于
usort
的方法来处理它

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

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

所需阵列可按如下方式在O(n)中构建:

$r = [];
for ($i = count($array) - 1; $i >= 0; --$i) {
  if ($i % 2) {
    $r []= $array[$i];
  } else {
    array_unshift($r, $array[$i]);
  }
}
/**
 * @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']);
}
代码从末尾开始迭代数组项。奇数索引下的项目(当
$i%2
为非零时)添加到
$r
的末尾,偶数索引下的项目添加到数组的开头


它是按
code
进行线性排序的,如何按
code

上面的代码将生成所需的数组,但项目不是按
code
按正态分布排序的!为了按
code
对真实正态分布中的项目进行排序,您需要计算正态分布的平均值,如下所示:

$r = [];
for ($i = count($array) - 1; $i >= 0; --$i) {
  if ($i % 2) {
    $r []= $array[$i];
  } else {
    array_unshift($r, $array[$i]);
  }
}
/**
 * @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']);
}

与平均值(
5
)的差值越大,数组索引越低。换言之,数组是按平均值(
5
)的“接近度”降序排列的。

谢谢你指出我对
正态分布的误解,看起来你的答案现在是最好的。但是如果有更新中描述的一些
通用
方法?