代码之家  ›  专栏  ›  技术社区  ›  Nalluri

根据C列表中的位置创建组合

  •  1
  • Nalluri  · 技术社区  · 6 年前

    我有个单子

        var list = new List<record>{
        new record{ flashid = 450, position = 5, value = "a"},
        new record{ flashid = 450, position = 6, value = "b"},
        new record{ flashid = 450, position = 7, value = "c"},
        new record{ flashid = 450, position = 7, value = "d"},
        new record{ flashid = 450, position = 7, value = "e"},
        new record{ flashid = 450, position = 8, value = "f"},
        new record{ flashid = 450, position = 9, value = "g"}
    }
    

    我有3个记录,位置为7,数值不同。从上面的列表中,我需要根据从1到10的位置为每个组合创建一个字符串。对于缺少的位置值,我们可以有任何临时字符。 因此,所需的输出将是

    ["....abcfg.","....abdfg.","....abefg."]
    

    我们可以用任何特殊的字符来代替点。

    谢谢

    2 回复  |  直到 6 年前
        1
  •  2
  •   Slava Utesinov    6 年前

    当然,您可以解决这个问题,如从注释到问题的链接中所述,但在本例中,您应该做一些乏味的工作-编写大量可重复的代码,如:

    var answer = (from pos1 in list.Where(x => x.position == 1)
                  from pos2 in list.Where(x => x.position == 2)
                  from pos3 in list.Where(x => x.position == 3)
                  ....
                  from pos10 in list.Where(x => x.position == 10)
                  select pos1.value + pos2.value + pos3.value + ... + pos10.value
                 ).ToList();
    

    因此,每次需要更改可能位置的数量时,都应该添加或删除相应的代码行。相反,你可以尝试 recursive approach .前一个解决方案不是动态的——您应该在编译时提前知道位置的数量,而第二个解决方案可以在运行时通过 limit 变量更改。

    static int limit = 10;
    
    static void Recursive(record record, List<string> bag, 
        Stack<record> stack, List<record> list)
    {
        stack.Push(record);
        if (record.position == limit)
        {
            var temp = new StringBuilder();
            foreach (var item in stack)
                temp.Insert(0, item.value);
            bag.Add(temp.ToString());
        }
        else            
            foreach (var item in list.Where(x => x.position == record.position + 1))
                Recursive(item, bag, stack, list);
        stack.Pop();            
    }
    
    static List<string> Solve(List<record> list)
    {
        for (var i = 1; i <= limit; i++)
            if (!list.Any(x => x.position == i))
                 list.Add(new record { position = i, value = "." });
    
        var bag = new List<string>();
        var stack = new Stack<record>();
        foreach (var record in list.Where(x => x.position == 1))
            Recursive(record, bag, stack, list);
    
        return bag;
    }
    

    用法:

    var list = new List<record>
    {
        new record { flashid = 450, position = 5, value = "a"},
        new record { flashid = 450, position = 6, value = "b"},
        new record { flashid = 450, position = 7, value = "c"},
        new record { flashid = 450, position = 7, value = "d"},
        new record { flashid = 450, position = 7, value = "e"},
        new record { flashid = 450, position = 8, value = "f"},
        new record { flashid = 450, position = 9, value = "g"}
    };
    
    var answer = Solve(list);       
    Console.WriteLine("[" + string.Join(", ", answer) + "]");       
    //output: [....abcfg., ....abdfg., ....abefg.]
    
        2
  •  0
  •   arekzyla    6 年前

    如果您想要纯LINQ解决方案,可以尝试以下操作。首先,扩展您的记录列表,使其包含每个缺少的位置:

    var extendedList = Enumerable
        .Range(1, 10)
        .GroupJoin(list, n => n, r => r.position, (n, g) => g
            .DefaultIfEmpty(new record { flashid = 450, position = n, value = "." }));
    

    这基本上是从1到10,每个数字对应的位置匹配和分组记录。如果一个组不包含任何匹配的值,那么当一个位置丢失时,会创建一个带有临时字符的默认记录。结果如下:

    record[10][] 
    { 
        record[] 
        { 
            record { flashid=450, position=1, value="." } 
        },
        (...)
        record[] 
        { 
            record { flashid=450, position=5, value="a" } 
        },
        (...)
        record[] 
        { 
            record { flashid=450, position=7, value="c" },
            record { flashid=450, position=7, value="d" },
            record { flashid=450, position=7, value="e" } 
        },
        (...)
    },
    

    现在要生成所有可能的值,可以尝试以下操作:

    var result = extendedList
        .Aggregate(Enumerable.Repeat("", 1), (a, c) => a
            .SelectMany(b => c
                .Select(d => b + d.value)));
    

    每个 Aggregate 迭代将单词序列从当前位置的字符组转换为另一个添加了单个字符的单词序列。就像这样:

    0. {""}
    1. {"."}
    2. {"."}
    3. {".."}
    4. {"..."}
    5. {"....a"}
    6. {"....ab"}
    7. {"....abc", "....abd", "....abe"}
    8. {"....abcf", "....abdf", "....abef"}
    9. {"....abcfg", "....abdfg", "....abefg"}
    10. {"....abcfg.", "....abdfg.", "....abefg."}
    

    您可以在这里尝试: https://dotnetfiddle.net/JCgYFP