【问题标题】:Getting unique combinations, in order, from a list with non-uniques从非唯一列表中按顺序获取唯一组合
【发布时间】:2018-03-23 07:40:50
【问题描述】:

我有一个无法解决的问题,我希望有人可以帮助我。

想象以下情况:

有一个人名列表。因此,每个人都是具有“名称”属性的对象。从该列表中,以随机顺序选择随机数量的人(因此并非所有人总是在选择中),并且每个人被选择不超过一次。但是,名称可能不是唯一的:列表中可能有多个名称为“Smith”的人。对于此示例,让我们假设每个名称只是字母表中的一个字母。所以我可能会收到以下选择:

[V、C、R、C、F、X、R、C]

而下一次的选择可能会完全不同。该选择中的每个元素都是不同的人,但有些名字出现了不止一次。

让我们添加数字来澄清:

[V, C1, R1, C2, F, X, R2, C3]

现在我需要所有可能的人组合,其中每个名字只出现一次,但要尊重他们在选择中列出的顺序。选择中的每个唯一名称都应在组合中。
例如,在这种情况下,我需要:

[V, C1, R1, F, X],
[V, R1, C2, F, X],
[V, R1, F, X, C3],
[V, C1, F, X, R2],
[V, C2, F, X, R2]
...

等等。人们的位置不应该改变(即 [C1, V, ...] 不行,因为 "V" 不应该在 "C1" 之后)。

我假设我需要递归和一些方法来跟踪名称,但这就是我的大脑开始融化的地方。 ;-) 我找到了以任何顺序获得所有可能排列的脚本,但没有这样的。

谁能帮帮我?

谢谢!

【问题讨论】:

    标签: javascript arrays algorithm


    【解决方案1】:

    您可以采用组合算法,该算法将一个项目(在检查相同的第一个字母是否不在临时结果集中)作为结果集,然后继续下一个索引,直到找到所需的长度或没有有更多项目可用。

    function getCombinations(array, size) {
    
        function fork(i, t) {
            if (t.length === size) {
                result.push(t);
                return;
            }
            if (i === array.length) {
                return;
            }
            if (!t.some(([c]) => c === array[i][0])) {
                fork(i + 1, t.concat([array[i]]));
            }
            fork(i + 1, t);
        }
    
        var result = [];
        fork(0, []);
        return result;
    }
    
    var data = ['V', 'C1', 'R1', 'C2', 'F', 'X', 'R2', 'C3'],
        result = getCombinations(data, 5);
    	
    console.log(result.map(a => a.join(' ')));

    【讨论】:

    • 抱歉让您久等了。我稍微调整了一下,但是这个效果很好。谢谢!!
    【解决方案2】:

    这是一个简单的非递归算法。

    list = ['V', 'C1', 'R1', 'C2', 'F', 'X', 'R2', 'C3']; //
    
    // build an index item => its positions
    // (in your case item[0] == item.name)
    
    let index = new Map;
    
    for (let [i, item] of list.entries())
        index.set(item[0], (index.get(item[0]) || new Set).add(i));
    
    // start with a single combination which is the initial list
    
    let combs = [list];
    
    // for each item and its positions...
    
    for (let [item, is] of index) {
    
        // generate a new set of combinations
    
        let combs2 = [];
    
        // for each position...
    
        for (let i of is) {
    
            // all positions of this item, except of the current one
    
            let toRemove = new Set([...is]);
            toRemove.delete(i);
    
            // for all combinations... 
    
            for (let c of combs) {
    
                // insert null at these positions
    
                combs2.push(c.map((x, j) => toRemove.has(j) ? null : x));
    
            }
        }
    
        // continue with the new set of combinations
    
        combs = combs2;
    }
    
    // once we're ready remove all null values
    
    combs = combs.map(c => c.filter(x => x !== null))
    
    // done
    
    for (let c of combs)
        console.log(c.join())

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-14
      • 1970-01-01
      • 1970-01-01
      • 2011-09-21
      相关资源
      最近更新 更多