按连续值排序多维数组的usort方法

4

我有一个数组:

$cards = [
    [
        "from" => "Barcelona",
        "to" => "Gerona Airport",        
    ],
    [
        "from" => "Stockholm",
        "to" => "New York JFK",          
    ],
    [
        "from" => "Gerona Airport",
        "to" => "Stockholm",          
    ],
    [
        "from" => "Madrid",
        "to" => "Barcelona",          
    ]
];

我需要对它进行排序,以使旅行持续进行,其中from与上一个to匹配,如果不匹配,则将其设置为起始点,例如:

Array (
    [0] => Array ( [from] => Madrid [to] => Barcelona )  
    [1] => Array ( [from] => Barcelona [to] => Gerona Airport )
    [2] => Array ( [from] => Gerona Airport [to] => Stockholm ) 
    [3] => Array ( [from] => Stockholm [to] => New York JFK ) 
)

我正在尝试使用usort

usort($cards, function ($a, $b) {
          return ( $a["to"] === $b["from"] ) ? -1 : 1;
      });

print_r($cards);

但是它没有按照描述的方式排序。有什么想法吗?


你能知道哪个数组是旅程的开始吗? - ezw
不,这并不重要,关键是将数组排序以进行连续的旅行。 - mshifo
3个回答

2
希望有更好的解决方案出现,但如果你按照数组中元素数量进行多次排序并返回相等或更大的值,即使你不知道开始位置或开始位置不是第一个元素,它也能够工作。由于usort遍历和比较的方式,返回相等或小于的值是不起作用的。请注意保留HTML标签。
foreach($cards as $card) {
    usort($cards, function ($a, $b) {
                      return ( $a["to"] === $b["from"] ) ? 0 : 1;
                  });
}

它可能需要更少的迭代次数,但将每个与其他所有对象进行比较似乎更为安全。

谢谢@Syscall。你的原始代码似乎可以工作,但是当我打乱数组时,它有时会失效。 - AbraCadaver
真的很好的答案 :) 你得到了我的 +1!我已经测试过我的代码,添加了许多其他城市并进行了洗牌,看起来可以工作(我会再次测试),但是你的更好! - Syscall
我正在寻找类似的东西 :) - mshifo

1

你可以采用递归的方式,并指定出发城市。

默认情况下,你从马德里开始,使用doSort($cards, $result);

如果你想要从“赫罗纳机场”继续旅行,可以使用doSort($cards, $result, "Gerona Airport");来开始。

$cards = [
    [
        "from" => "Barcelona",
        "to" => "Gerona Airport",
    ],
    [
        "from" => "Stockholm",
        "to" => "New York JFK",
    ],
    [
        "from" => "Gerona Airport",
        "to" => "Stockholm",
    ],
    [
        "from" => "Madrid",
        "to" => "Barcelona",
    ]
];
$result = [];

function doSort($cards, &$result, $start = "Madrid") {
    foreach ($cards as $key => $card) {
        if ($card["from"] === $start) {
            $result[] = $card;
            doSort($cards, $result, $card["to"]);
        }
    }
}
doSort($cards, $result);
print_r($result);

Php输出演示

这会给你:

Array
(
    [0] => Array
        (
            [from] => Madrid
            [to] => Barcelona
        )

    [1] => Array
        (
            [from] => Barcelona
            [to] => Gerona Airport
        )

    [2] => Array
        (
            [from] => Gerona Airport
            [to] => Stockholm
        )

    [3] => Array
        (
            [from] => Stockholm
            [to] => New York JFK
        )

)

我尝试了一个更长的洗牌数组,这似乎效果很好。 - AbraCadaver

0

这里有一种方法。通过迭代,找到起点并搜索路径:

// 1. Find the start
$start = null;
$starts = array_column($cards,'from');
$ends = array_column($cards,'to');
foreach ($cards as $card) {
    if (!in_array($card['from'], $ends)) $start=$card;
}
// 2. Find way
$way=[$start];
while (count($cards)>1) {
    $found = false ;
    foreach ($cards as $k => $card) {
        if ($card['from'] == $start['to']) {
            $way[] = $card;
            $start = $card;
            unset($cards[$k]);
            $found = true ;
            break 1;
        }
    }
    if (!$found) { echo "Impossible to use all cards.\n" ; break ; }
}
print_r($way);

输出:

    Array (
    [0] => Array ([from] => Madrid [to] => Barcelona )
    [1] => Array ([from] => Barcelona [to] => Gerona Airport )
    [2] => Array ([from] => Gerona Airport [to] => Stockholm )
    [3] => Array ([from] => Stockholm [to] => New York JFK )
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接