function getCombinations(_list) {
var fn = function(active, rest, a) {
if (!active.length && !rest.length)
return;
if (!rest.length) {
a.push(active);
} else {
fn(active.concat(rest[0]), rest.slice(1), a);
fn(active, rest.slice(1), a);
}
return a;
}
return fn([], _list, []);
}
var list = [1, 2, 3, 4]
console.log(getCombinations(list));

返回一个2D数组,每个组合都填充...
[ [ 1, 2, 3, 4 ]
, [ 1, 2, 3 ]
, [ 1, 2, 4 ]
, [ 1, 2 ]
, [ 1, 3, 4 ]
, [ 1, 3 ]
, [ 1, 4 ]
, [ 1 ]
, [ 2, 3, 4 ]
, [ 2, 3 ]
, [ 2, 4 ]
, [ 2 ]
, [ 3, 4 ]
, [ 3 ]
, [ 4 ]
]
但我想要以下订单
[ [ 1 ]
, [ 1, 2 ]
, [ 1, 2, 3]
, [ 1, 2, 3, 4 ]
, [ 1, 2, 4]
, [ 1, 3 ]
, [ 1, 3, 4 ]
, [ 1, 4 ]
, [ 2 ]
, ...
, [ 4 ]
]
我尝试使用.sort
,但按字母顺序对组合进行排序
getCombinations([ 1, 2, 10 ]).sort()
// [ [ 1 ]
// , [ 1, 10 ]
// , [ 1, 2 ]
// , [ 1, 2, 10 ]
// , [ 10 ]
// , [ 2 ]
// , [ 2, 10 ]
// ]
但这不是我想要的订单。
如何对数组进行排序,以便以数字方式处理数组的内容,结果与上面提到的顺序相同?
答案 0 :(得分:3)
之后可以使用而不是排序,这是一个直接创建所需组合作为排序结果的函数。
function getCombinations(list) {
function iter(index, values) {
var temp = values.concat(list[index]);
result.push(temp);
if (++index < list.length) {
iter(index, temp);
iter(index, values);
}
}
var result = [];
iter(0, []);
return result;
}
var list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
result = getCombinations(list);
console.log(result.length);
console.log(result.map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:2)
您可以将比较器函数传递给实现所需排序逻辑的sort()
。
arr.sort((one, other) => {
let minL = Math.min(one.length, other.length);
for (let i = 0; i < minL; i++) {
if (one[i] != other[i]) return one[i] - other[i];
}
return one.length - other.length;
});
答案 2 :(得分:2)
这是用功能编程标记的,所以我想我会展示一种以正确的顺序生成组合的功能方法。
通过功能,我的意思是使用仅运行其输入参数的函数(而不是依赖于外部状态)并返回一个值(而不是依赖于变异)。这与命令式风格形成鲜明对比。
使用Array.prototype.sort
既不必要也不实用(它会改变其输入),因此不会在此答案中使用它。
你还提到自从你编写了递归程序以来已经有一段时间了。这应该让轮子再次旋转!
const identity = x =>
x
const concat = (xs, ...ys) =>
ys.length === 0
? xs
: xs.concat (concat (...ys))
const subsets = ([ x, ...xs ], _return = identity) =>
xs.length === 0
? _return ([ [ x ] ])
: subsets
( xs
, ss =>
_return ( concat ( [ [ x ] ]
, ss.map (s => concat ([ x ], s))
, ss
)
)
)
for (const set of subsets ([ 1, 2, 3, 4 ]))
console.log (set)
实现正确的排序
[ 1 ]
[ 1, 2 ]
[ 1, 2, 3 ]
[ 1, 2, 3, 4 ]
[ 1, 2, 4 ]
[ 1, 3 ]
[ 1, 3, 4 ]
[ 1, 4 ]
[ 2 ]
[ 2, 3 ]
[ 2, 3, 4 ]
[ 2, 4 ]
[ 3 ]
[ 3, 4 ]
[ 4 ]
相关:Power Set - 虽然此程序无法生成正确的顺序,但它的简化表单向您展示了如何开始考虑自己解决问题。 concat
现在是一个基本的二进制操作,powerSet
简化了逻辑分支。
const identity = x =>
x
const concat = (xs, ys) =>
xs.concat (ys)
const None =
Symbol ()
const powerSet = ([ x = None, ...xs ], _return = identity) =>
x === None
? _return ([ [] ]) // base case: no X
: powerSet // inductive case: at least one X
( xs
, ss =>
_return ( concat ( ss.map (s => concat ([ x ], s))
, ss
)
)
)
console.log (powerSet ([ 'x', 'y', 'z' ]))
// [ [ 'x', 'y', 'z' ]
// , [ 'x', 'y' ]
// , [ 'x', 'z' ]
// , [ 'x' ]
// , [ 'y', 'z' ]
// , [ 'y' ]
// , [ 'z' ]
// , []
// ]
尽管不那么复杂,powerSet
甚至可以使用空输入,使其成为total function
getCombinations ([])
// => undefined
subsets ([])
// => [ [ undefined ] ]
powerSet ([])
// => [ [] ]
答案 3 :(得分:0)
你可以使用这样的比较函数:
{{1}}
答案 4 :(得分:-1)
你可以模仿这个,通过使用点数或你喜欢的任何其他角色连接数字值来使用自然排序。
import re
s1 = 'H12-H121'
pat = r'^H12'
print(re.sub(pat,"G12",s1))
G12-H121
这是一种使用浮点排序的简写方法。
注意:这是一个技巧,你可以通过更大的列表获得浮点精度错误。
var list = [
[ 1, 2, 3, 4 ],
[ 1, 2, 3 ],
[ 1, 2, 4 ],
[ 1, 2 ],
[ 1, 3, 4 ],
[ 1, 3 ],
[ 1, 4 ],
[ 1 ],
[ 2, 3, 4 ],
[ 2, 3 ],
[ 2, 4 ],
[ 2 ],
[ 3, 4 ],
[ 3 ],
[ 4 ]
];
function versionNumberSort(a, b) {
return a.join('.').localeCompare(b.join('.'))
}
console.log(list.sort(versionNumberSort).map(l => l.join(', ')).join('\n'));
.as-console-wrapper { top: 0; max-height: 100% !important; }
var list = [
[ 1, 2, 3, 4 ],
[ 1, 2, 3 ],
[ 1, 2, 4 ],
[ 1, 2 ],
[ 1, 3, 4 ],
[ 1, 3 ],
[ 1, 4 ],
[ 1 ],
[ 2, 3, 4 ],
[ 2, 3 ],
[ 2, 4 ],
[ 2 ],
[ 3, 4 ],
[ 3 ],
[ 4 ]
];
function sortNumberArrays(a, b) {
return parseFloat('0.' + a.join('')) - parseFloat('0.' + b.join(''));
}
console.log(list.sort(sortNumberArrays).map(l => l.join(', ')).join('\n'));