我有一个像这样的数组:
var groups = [
['one', 'three', 'four'],
['two', 'three', 'six', 'seven'],
['three', 'four', 'five'],
]
由此我需要根据给出的顺序推导出适当的值序列(我给出了数字以便于举例)。换句话说,由于每个数组都缺少数据,因此需要引用其他数组以获得所有组的最佳序列。理想输出:
['one', 'two', 'three', 'four', 'five', 'six', 'seven'];
我可以写这个,但我完全相信这是一个非常常见的算法。我只是不知道它的名字。任何想法(或解决它的简单方法)?
答案 0 :(得分:2)
一种可能的方法是使用topological sorting在有向无环图中找到最短路径:
结果路径是您的解决方案。请注意,您必须确保您的组定义非循环图。
答案 1 :(得分:2)
工作原理
path = [ [ "one", "three" ], [ "three", "four" ], [ "two", "three" ], [ "three", "six" ], [ "six", "seven" ], [ "three", "four" ], [ "four", "five" ] ] Operation Result ------------------------------------ ---------------------------------- 0 push(one) one 1 splice(1, 0, three) one,three 0 push(three) one,three,three 0 splice(2, 1) delete last double one,three 1 splice(2, 0, four) one,three,four 0 splice(1, 0, two) one,two,three,four 1 splice(2, 0, three) one,two,three,three,four 1 splice(3, 1) delete last double one,two,three,four 0 push(three) one,two,three,four,three 0 splice(4, 1) delete last double one,two,three,four 1 splice(3, 0, six) one,two,three,six,four 0 push(six) one,two,three,six,four,six 0 splice(5, 1) delete last double one,two,three,six,four 1 splice(4, 0, seven) one,two,three,six,seven,four 0 splice(5, 0, three) one,two,three,six,seven,three,four 0 splice(5, 1) delete last double one,two,three,six,seven,four 1 splice(3, 0, four) one,two,three,four,six,seven,four 1 splice(6, 1) delete last double one,two,three,four,six,seven 0 push(four) one,two,three,four,six,seven,four 0 splice(6, 1) delete last double one,two,three,four,six,seven 1 splice(4, 0, five) one,two,three,four,five,six,seven
基本上,它获取具有开始/目标对的数组中所有组合项的路径。然后走下路径,对于每个开始和目标,进行查找以找到前任或后继者。如果找到前任,则在索引处插入项目,如果在索引后插入后继项。如果未找到,则将项目推送到数组的末尾。
由于插入了每个路径的开始和目标,结果比想要的更长(2x)。因此删除了最后一个重复的项目。
var groups = [
['one', 'three', 'four'],
['two', 'three', 'six', 'seven'],
['three', 'four', 'five'],
];
function combination(a, r) {
r = r || [];
a.reduce(function (res, el) {
el.forEach(function (item, i) {
i && res.push([el[i - 1], item]);
});
return res;
}, []).forEach(function (el) {
function lookup(n, m, offset) {
var index = r.indexOf(n);
~index ? r.splice(index + offset, 0, m) : r.push(m);
r.indexOf(m) !== r.lastIndexOf(m) && r.splice(r.lastIndexOf(m), 1);
}
lookup(el[1], el[0], 0);
lookup(el[0], el[1], 1);
});
return r;
}
console.log(combination(groups));
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 2 :(得分:1)
让我用php写一下。我尝试评论所有行
$groups = [
['one', 'three', 'four'],
['two', 'three', 'six', 'seven'],
['three', 'four', 'five'],
];
$maxl = 0; // max length of nested arrays
foreach($groups as $item) // walk through array
if ((count($item) > $maxl)) // if current array is longer
$maxl = count($item); // save it's length
$result = []; // will be result
for ($i = 0; $i < $maxl; $i++) // vertical slice of the array
for ($j = 0; $j < count($groups); $j++) // loop through nested arrays
if(isset($groups[$j][$i]) && // if such element is present
!in_array($groups[$j][$i], $result)) // and not in result yet
$result[] = $groups[$j][$i]; // add it
print_r($result);
但是我无法理解五和六的顺序,所以结果是:
Array
(
[0] => one
[1] => two
[2] => three
[3] => four
[4] => six
[5] => five
[6] => seven
)
答案 3 :(得分:1)
你想要的是https://github.com/emmetio/emmet/blob/master/lib/snippets.json,但要注意它有多种解决方案。
在您提供的示例中,您的关系仅提供以下约束:
这意味着以下解决方案是正确的:
计算所提供示例的拓扑排序总数留给读者。