你在这里所做的是迭代所有排列14 个离散值的列表。
一般来说,要访问离散事物列表的所有排列,您需要访问列表中的每个元素。对于每个元素,形成一个包含所有元素的新列表other原始列表的元素。得到所有的排列that列表,将元素添加到每个元素之前,您就获得了可以以该特定元素开头的原始列表的所有排列。当你完成所有元素后,你就完成了。
当然,查找包含一个元素的列表的所有排列是一项简单的任务。
因此我们得到的是这样的:
function forEachPermutation(list, operation) {
function pluckElement(list, index) {
var e = list[index];
var l = [];
for (var i = 0; i < list.length; ++i)
if (i !== index) l.push(list[i]);
return { element: e, remainder: l };
}
function permute(partial, remainder) {
if (remainder.length === 0)
operation(partial);
else {
for (var i = 0; i < remainder.length; ++i) {
var plucked = pluckElement(remainder, i);
partial.push(plucked.element);
permute(partial, plucked.remainder);
partial.length--;
}
}
}
permute([], list);
}
它的作用是递归地执行我上面描述的操作。 “pluckElement”函数从列表中返回一个元素,并且rest该列表中的。然后,“permute”函数要么执行对原始列表的完整排列传入的操作(当它注意到剩余列表为空时),要么使用它传递的列表的每个元素递归地调用自身。
要使用该功能,您只需执行以下操作:
forEachPermutation([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], check);
edit— 如果您只想从原始列表中提取一定数量的值,则必须修改上述内容;稍等片刻。
好的 - 如果您想传入(例如)14 个元素的列表,但为 14 个(例如)7 个元素的每个不同列表调用“操作”函数,您可以按如下方式修改该函数。外部“forEachPermutation”函数将采用额外的“len”参数,以告诉它所需的字符串长度。然后,“permute”函数将检查“partial.length”是否是目标长度,而不是检查空余数。
function forEachPermutation(list, len, operation) {
function pluckElement(list, index) {
var e = list[index];
var l = [];
for (var i = 0; i < list.length; ++i)
if (i !== index) l.push(list[i]);
return { element: e, remainder: l };
}
function permute(partial, remainder) {
if (partial.length === len)
operation(partial);
else {
for (var i = 0; i < remainder.length; ++i) {
var plucked = pluckElement(remainder, i);
partial.push(plucked.element);
permute(partial, plucked.remainder);
partial.length--;
}
}
}
permute([], list);
}
你会这样称呼它
forEachPermutation([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 7, check);
另一个编辑— 如果出于某种原因你想要save“操作”函数处理每个排列后的排列,那么我们必须考虑正在使用的部分数组被覆盖的事实。对“操作”的调用可以更改:
if (partial.length === len)
operation(partial.slice(0));
这会生成“部分”数组的副本,以便每次调用“操作”时都会获得自己的数组来使用。当然,这会让这个过程变慢。