获取所有可能的元素组合
Get every possible combination of elements
如何获得数组中 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 和/或柯里化是否有实用的方法? Derive every possible combination of elements in array
您不需要任何库,您可以使用嵌套循环在 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]]);
借用自Haskell:
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
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))
PS。 LiveScript 对此有一个很好的语法:
http://homam.github.io/try-livescript/#welcome/lists
选择蚂蚁大小的子集:Ramda code
var g = (xs, n) =>
n == 0 ? [[]] :
R.isEmpty(xs) ? [] :
R.concat(
R.map(R.prepend(R.head(xs)), g(R.tail(xs), n - 1))
, g(R.tail(xs), n)
)
g(as, 3)
这适用于任何长度的排列,只需将其调整为在 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], []);
如果您只想要两个元素,Oriol 的 应该可以。但是如果你想要扩展到任何大小子组的东西,像这样的东西可能会做:
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 in Ramda's Gitter room。在那里我建议它过度紧张,但那是为了完整的排列。它似乎适合 n 组合。
您可以在 Ramda REPL.
上看到它的实际效果
这是一个优雅的解决方案:
// 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]]
如何获得数组中 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 和/或柯里化是否有实用的方法? Derive every possible combination of elements in array
您不需要任何库,您可以使用嵌套循环在 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]]);
借用自Haskell:
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
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))
PS。 LiveScript 对此有一个很好的语法: http://homam.github.io/try-livescript/#welcome/lists
选择蚂蚁大小的子集:Ramda code
var g = (xs, n) =>
n == 0 ? [[]] :
R.isEmpty(xs) ? [] :
R.concat(
R.map(R.prepend(R.head(xs)), g(R.tail(xs), n - 1))
, g(R.tail(xs), n)
)
g(as, 3)
这适用于任何长度的排列,只需将其调整为在 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], []);
如果您只想要两个元素,Oriol 的
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 in Ramda's Gitter room。在那里我建议它过度紧张,但那是为了完整的排列。它似乎适合 n 组合。
您可以在 Ramda REPL.
上看到它的实际效果这是一个优雅的解决方案:
// 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]]