У меня есть 2-мерный массив, в котором значения ...

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 (не совсем уверен), потому что API матрицы расстояний Google иногда возвращает большие значения для одного и того же источника и пункта назначения, поэтому я заменил его на 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;
}
1
Saifur Rahman Mohsin 8 Окт 2018 в 07:19

2 ответа

Лучший ответ

Я смог найти решение этой проблемы самостоятельно. Публикация здесь, если кто-то еще сталкивается с той же проблемой:

$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 мог бы сделать трюк, но он отлично работает).

0
Saifur Rahman Mohsin 10 Окт 2018 в 09:54

Если вам подходит изменение меток столбцов матрицы - вы можете выполнить такую сортировку:

$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
0
Agnius Vasiliauskas 8 Окт 2018 в 11:12