获得每种可能的元素组合

时间:2016-02-28 20:37:09

标签: javascript ramda.js

如何获得数组中2个元素的所有可能组合?

例如:

[
    1, 
    2, 
    3, 
    4 
]

becomes

[
    [1, 2], 
    [1, 3], 
    [1, 4], 
    [2, 1], 
    [2, 3], 
    [2, 4],
    [3, 1],
    [3, 2],
    [3, 4],
    [4, 1],
    [4, 2],
    [4, 3] 
]

这个答案使用蛮力但是有一种功能性的方式与Ramda和/或currying? Derive every possible combination of elements in array

5 个答案:

答案 0 :(得分:5)

这是一个优雅的解决方案:

//    permutations :: Number -> [a] -> [[a]]
const permutations = R.compose(R.sequence(R.of), R.flip(R.repeat));

用法示例:

permutations(2, [1, 2, 3, 4]);
// => [[1, 1], [1, 2], ..., [4, 3], [4, 4]]

permutations(3, [1, 2, 3, 4]);
// => [[1, 1, 1], [1, 1, 2], ..., [4, 4, 3], [4, 4, 4]]

答案 1 :(得分:3)

借用Haskell:

INET6_*

这是my Ramda version

as = [1, 2, 3]

f xs = do
  a <- xs
  b <- xs
  return $ if a == b then [] else [a, b]

main = print $ filter (not . null) . f $ as

PS。 LiveScript有一个很好的语法: http://homam.github.io/try-livescript/#welcome/lists

用于选择蚂蚁大小的子集:Ramda code

var as = [1, 2, 3, 4]

var f = xs => 
  R.pipe(
      R.chain(a => R.map(b => a == b ? [] : [a, b])(xs))
    , R.filter(R.pipe(R.isEmpty, R.not))
  )(xs)

console.log(f(as))

答案 2 :(得分:1)

您不需要任何库,您可以使用嵌套循环在vanilla-js中轻松完成:

var arr = [1, 2, 3, 4],
    result = [];
for(var i=0; i<arr.length; ++i)
  for(var j=0; j<arr.length; ++j)
    if(i !== j)
      result.push([arr[i], arr[j]]);

答案 3 :(得分:0)

这适用于任何长度的排列,只需调整它以在2处切断。

function permutate(input, output) {
  if (input.length === 0) {
    document.body.innerHTML += "<div>" + output + "</div>";
  }

  for (var i = 0; i < input.length; i++) {
    output.push(input[i]);
    permutate(input.slice(0, i).concat(input.slice(i + 1)), output);
    output.pop();
  }
}

permutate([1, 2, 3, 4], []);

答案 4 :(得分:0)

如果您只想要两个元素,Oriol的answer应该没问题。但是如果你想要扩展到任何大小的子组,可能会这样:

const permutations = (n, tokens, subperms = [[]]) =>
  n < 1 || n > tokens.length ?
    subperms        :
    R.addIndex(R.chain)((token, idx) => permutations(
      n - 1,
      R.remove(idx, 1, tokens), 
      R.compose(R.map, R.append)(token)(subperms)
    ), tokens);


permutations(2, [1, 2, 3, 4]);
//=> [[1, 2], [1, 3], [1, 4], [2, 1], [2, 3], [2, 4], 
//    [3, 1], [3, 2], [3, 4], [4, 1], [4, 2], [4, 3]]

permutations(3, [1, 2, 3, 4]);
//=> [[1, 2, 3], [1, 2, 4], [1, 3, 2], [1, 3, 4], [1, 4, 2], [1, 4, 3],
//    [2, 1, 3], [2, 1, 4], [2, 3, 1], [2, 3, 4], [2, 4, 1], [2, 4, 3],
//    [3, 1, 2], [3, 1, 4], [3, 2, 1], [3, 2, 4], [3, 4, 1], [3, 4, 2],
//    [4, 1, 2], [4, 1, 3], [4, 2, 1], [4, 2, 3], [4, 3, 1], [4, 3, 2]]

此版本略微改编自I presented中的一个Ramda's Gitter room。在那里,我建议它是过度的,但这是完全排列。这似乎适合于n组合。

您可以在 Ramda REPL 上看到它。