推断组序列的算法名称

时间:2015-06-25 01:36:52

标签: javascript arrays algorithm object

我有一个像这样的数组:

var groups = [
  ['one', 'three', 'four'],
  ['two', 'three', 'six', 'seven'],
  ['three', 'four', 'five'],
]

由此我需要根据给出的顺序推导出适当的值序列(我给出了数字以便于举例)。换句话说,由于每个数组都缺少数据,因此需要引用其他数组以获得所有组的最佳序列。理想输出:

['one', 'two', 'three', 'four', 'five', 'six', 'seven'];

我可以写这个,但我完全相信这是一个非常常见的算法。我只是不知道它的名字。任何想法(或解决它的简单方法)?

4 个答案:

答案 0 :(得分:2)

一种可能的方法是使用topological sorting在有向无环图中找到最短路径:

  1. 为每个唯一的“字”
  2. 定义一个节点
  3. 定义从左(源)到右(接收器)的组中相邻“单词”之间的有向边
  4. 计算每个边缘的重量作为一个函数,测量一组中两个单词彼此相邻的次数(需要在此处进行实验)
  5. 计算构建的DAG的topological orderings集。
  6. 计算DAG中的shortest path
  7. 结果路径是您的解决方案。请注意,您必须确保您的组定义非循环图。

答案 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,但要注意它有多种解决方案。

在您提供的示例中,您的关系仅提供以下约束:

  • 1和2在3
  • 之前
  • 4在5
  • 之前
  • 6在7之前
  • 4,5,6和7在3
  • 之后

这意味着以下解决方案是正确的:

  • 2 1 3 4 6 7 5
  • 1 2 3 6 7 4 5
  • 2 1 3 6 4 7 5

计算所提供示例的拓扑排序总数留给读者。