代码之家  ›  专栏  ›  技术社区  ›  Cristian Diaconescu

Linq是否返回两个列表中的所有元素对?

  •  15
  • Cristian Diaconescu  · 技术社区  · 14 年前

    给定列表 l1 = {1, 2} l2 = {4, 5, 6 } 我想得到一个包含以下元素的新列表:

    rez = { {1, 4}, {1, 5}, {1, 6}, {2, 4}, {2, 5}, {2, 6} }
    

    建议?

    7 回复  |  直到 14 年前
        1
  •  34
  •   Eric Lippert    11 年前

    是的,这是可能的。Eric Lippert就这个话题写了一篇非常好的文章:

    Computing a Cartesian Product with LINQ

    如果只有两个列表,那么可以直接使用多个 from 这样地:

    from a in s1 
    from b in s2 
    select new [] { a, b};
    

    甚至:

    s1.SelectMany(a => s2.Select(b => new [] { a, b }));
    

    public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
    {
        IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
        return sequences.Aggregate(
            emptyProduct,
            (accumulator, sequence) =>
            from accseq in accumulator
            from item in sequence
            select accseq.Concat(new[] { item }));
    }
    

    var l1 = new[] {1, 2};
    var l2 = new[] {4, 5, 6};
    var l3 = new[] {7, 3};
    
    foreach (var result in new []{l1,l2,l3}.CartesianProduct())
    {
        Console.WriteLine("{"+string.Join(",",result)+"}");
    }
    

    并获得:

    {1,4,7}
    {1,4,3}
    {1,5,7}
    {1,5,3}
    {1,6,7}
    {1,6,3}
    {2,4,7}
    {2,4,3}
    {2,5,7}
    {2,5,3}
    {2,6,7}
    {2,6,3}
    
        2
  •  4
  •   BozoJoe Doug L.    7 年前

    埃里克·利珀特已经帮你做了!

    http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx

    你可能只想知道 SelectMany

    var s1 = new[] {a, b}; 
    var s2 = new[] {x, y, z}; 
    
    
    var product = 
    from first in s1 
    from second in s2 
    select new[] { first, second };
    

    product.SelectMany(o=>o);

    static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) 
    { 
      // base case: 
      IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() }; 
      foreach(var sequence in sequences) 
      { 
        var s = sequence; // don't close over the loop variable 
        // recursive case: use SelectMany to build the new product out of the     old one 
        result = 
          from seq in result 
          from item in s 
          select seq.Concat(new[] {item}); 
      } 
      return result; 
    }
    

    product.CartesianProduct();

        3
  •  3
  •   Justin Niessner    14 年前
    var result = from a in l1
                 from b in l2
                 select new[] { a, b }
    
        4
  •  2
  •   Greg    14 年前

    干得好;

    var rez =  from first in l1 
               from second in l2 
               select new[] { first, second };
    
        5
  •  1
  •   cirons42    14 年前

    像这样的东西可以满足你的需要。

    var l1 = new List<int>{1,2};
    var l2 = new List<int>{4,5,6};
    
    var p = from n in l1
            from m in l2
            select new { Fst = n, Scd = m };
    

    根据这个答案,元组{x,y}是匿名类型。

        6
  •  1
  •   Eric Lippert    14 年前

    伟大的文章埃里克利珀特-请参阅其他答案的链接。 更妙的是,这是我在阅读本页答案之前的第一次尝试:)

    简而言之:

    var rez = 
        from e1 in l1
        from e2 in l2 
        select new {e1, e2};
    
        7
  •  -3
  •   Jader Dias    14 年前

    l1.Join(l2, a => 1, b => 1, (a, b) => new [] { a, b });