在 PHP 中正确获取此数组的排序顺序

Properly getting the sorting order of this array in PHP

我有一个二维数组,其中的值...

9999999999999999  3201  4584  4821  1628  1218  1786  4738  4897
3122  9999999999999999  1400  1638  1797  2756  3323  5310  5472
4523  1400  9999999999999999  237 3198  4156  4723  6711  6872
4760  1638  237 9999999999999999  3435  4394  4961  6948  7110
1324  1846  3247  3485  9999999999999999  958 1525  3931  4093
932 2854  4273  4510  1002  9999999999999999  567 4873  5034
1499  3422  4840  5078  1569  567 9999999999999999  5440  5602
5061  5359  6760  6998  4019  4959  5526  9999999999999999  161
5233  5531  6931  7169  4190  5130  5697  171 9999999999999999

这是代码中的相同数组:

array:9 [
  0 => array:9 [
    0 => 9999999999999999
    1 => 3122
    2 => 4523
    3 => 4760
    4 => 1324
    5 => 932
    6 => 1499
    7 => 5061
    8 => 5233
  ]
  1 => array:9 [
    0 => 3201
    1 => 9999999999999999
    2 => 1400
    3 => 1638
    4 => 1846
    5 => 2854
    6 => 3422
    7 => 5359
    8 => 5531
  ]
  2 => array:9 [
    0 => 4584
    1 => 1400
    2 => 9999999999999999
    3 => 237
    4 => 3247
    5 => 4273
    6 => 4840
    7 => 6760
    8 => 6931
  ]
  3 => array:9 [
    0 => 4821
    1 => 1638
    2 => 237
    3 => 9999999999999999
    4 => 3485
    5 => 4510
    6 => 5078
    7 => 6998
    8 => 7169
  ]
  4 => array:9 [
    0 => 1628
    1 => 1797
    2 => 3198
    3 => 3435
    4 => 9999999999999999
    5 => 1002
    6 => 1569
    7 => 4019
    8 => 4190
  ]
  5 => array:9 [
    0 => 1218
    1 => 2756
    2 => 4156
    3 => 4394
    4 => 958
    5 => 9999999999999999
    6 => 567
    7 => 4959
    8 => 5130
  ]
  6 => array:9 [
    0 => 1786
    1 => 3323
    2 => 4723
    3 => 4961
    4 => 1525
    5 => 567
    6 => 9999999999999999
    7 => 5526
    8 => 5697
  ]
  7 => array:9 [
    0 => 4738
    1 => 5310
    2 => 6711
    3 => 6948
    4 => 3931
    5 => 4873
    6 => 5440
    7 => 9999999999999999
    8 => 171
  ]
  8 => array:9 [
    0 => 4897
    1 => 5472
    2 => 6872
    3 => 7110
    4 => 4093
    5 => 5034
    6 => 5602
    7 => 161
    8 => 9999999999999999
  ]
]

我想要实现的是根据最接近的顺序找到这个数组的排序顺序。每行包含一个地方到另一个地方的距离。

换句话说,数组类似于:

        China    India    USA    Japan
China     0        50     4000    2000
India     50       0      4100    2100
USA      4050     4120      2     3000
Japan    2010     1950    2997     0

如你所见,self 的值为 0,有时它是一个小数字,如 2-10(你不太确定)因为 Google 距离矩阵 API 有时 returns 对于相同的起点和终点也有很大的价值,这就是为什么我将它替换为 9999999999999999 在我上面的原始数组的整个对角线上。

目标是根据距离进行排序。第一个条目是起点,因此对于上面的假设数组,它将是: [0 1 3 2] 即从中国到印度,然后印度到日本,日本到美国。我的目标是最终使用 array_multisort 仅对带有地名的键进行排序,以便正确排序。

我想出的代码没有像我希望的那样工作:

$order = [0];
$i = 0;
$nextItemToProcessIndex = 0;
foreach($tempMatrix as $key => $entry) {
    $tempMatrix[$key][$key] = PHP_INT_MAX;
}
while(!empty($tempMatrix)) {
    $closestItemIndex = array_search(min($tempMatrix[$nextItemToProcessIndex]), $tempMatrix[$nextItemToProcessIndex]);
    array_push($order, $closestItemIndex);
    $this->pull_item($tempMatrix, $nextItemToProcessIndex);
    $nextItemToProcessIndex = $closestItemIndex - 1;
    $i++;
}
dd($order);
...
...
public function pull_item(&$array, $offset) {
    array_walk($array, function (&$v) use ($offset) {
        array_splice($v, $offset, 1);
    });
    $row = array_splice($array, $offset, 1);
    return $row;
}

如果您可以更改矩阵列标签 - 您可以这样进行排序:

$dist = [
    "China" => ['China' =>    0, 'India' =>   50,  'USA' => 4000, 'Japan' => 2000],
    "India" => ['China' =>   50, 'India' =>    0,  'USA' => 4100, 'Japan' => 2100],
    "USA  " => ['China' => 4050, 'India' => 4120,  'USA' =>    2, 'Japan' => 3000],
    "Japan" => ['China' => 2010, 'India' => 1950,  'USA' => 2997, 'Japan' =>    0]
];

// sort columns by distance
foreach ($dist as $key => $value) {
    asort($dist[$key]);
}

// display distances matrix
foreach ($dist as $row_c => $data) {
    $row1 = "\t";
    $row2 = $row_c . " : ";
    foreach ($data as $col_c => $col_dist) {
        $row1 .= $col_c . "\t";
        $row2 .= $col_dist . "\t";
    }
    echo "{$row1}\n{$row2}\n\n";
}

输出:

        China   India   Japan   USA 
China : 0         50    2000    4000

        India   China   Japan   USA 
India : 0         50    2100    4100

        USA     Japan   China   India   
USA   : 2        3000   4050    4120

        Japan   India   China   USA 
Japan : 0        1950   2010    2997

我自己找到了解决方案。如果其他人遇到同样的问题,请在此处发布:

$nextItemToProcess = 0;
$order = [0];

foreach(range(0, count($tempMatrix) - 2) as $i) {
    if(count(array_diff_key($tempMatrix[$nextItemToProcess], $order)) == 1) {
      $order = array_merge($order, array_diff(range(0, count($tempMatrix)-1), $order));
      break;
    }

    $diffArray = array_diff_key($tempMatrix[$nextItemToProcess], array_flip($order));
    $closestItemIndex = array_search(min($diffArray), $tempMatrix[$nextItemToProcess]);
    array_push($order, $closestItemIndex);
    $nextItemToProcess = $closestItemIndex;
}

$ascOrigins = [];
foreach($order as $i) {
    array_push($ascOrigins, $arrOrigins[$i]);
}

ascOrigins 是按位置距离升序排列的数组。我以为我可以使用 php 的 array_multisort 但它没有用,因为在这里我根据顺序值对 arr 的键进行排序。 (我知道 array_flip 可以解决这个问题,但这很好用)。