2011-09-08 23 views
1

合併多套我有3套Linq中,像這樣的:如何在LINQ

struct Index 
{ 
    string code; 
    int indexValue; 
} 

List<Index> reviews 
List<Index> products 
List<Index> pages 

這些名單有不同的代碼。

我想這些集合合併如下:

  • 採取先在評論
  • 在第一個在產品
  • 採取先在網頁
  • 參加審查 第二-...等等,請注意這些列表的大小不一樣。

我該如何在Linq中做到這一點?

編輯︰等待,有沒有更改來做到這一點沒有NET 4.0?

非常感謝您

+3

都是3個相同的大小?如果是這樣,我認爲你正在尋找linq中的Zip方法http://community.bartdesmet.net/blogs/bart/archive/2008/11/03/c-4-0-feature-focus-part-3 -intermezzo-linq-s-new-zip-operator.aspx – BlackTigerX

+0

還有聯合方法,但不知道你在做什麼 – BlackTigerX

+0

你要在哪裏存儲新的對象,你能說一點點合併你的意思嗎? – Tarik

回答

4

你可以使用Zip聽從你的命令。

var trios = reviews 
    .Zip(products, (r, p) => new { Review = r, Product = p }) 
    .Zip(pages, (rp, p) => new { rp.Review, rp.Product, Page = p }); 

編輯:

對於.NET 3.5,這是可能實現Zip很容易:但也有少數疑難雜症秒。 Jon Skeet撰寫了一篇關於如何實現LINQ to object運算符(用於教育目的)的系列文章,其中包括this post, on Zip。整個系列的源代碼edulinq可以是found on Google Code

+0

有沒有更改來做到這一點,沒有NET 4.0,謝謝:) – Vimvq1987

+1

巴特德斯梅特有一個博客文章只是:http://community.bartdesmet.net/blogs/bart/archive/2008/11/03/ c-4-0-feature-focus-part-3-intermezzo-linq-s-new-zip-operator.aspx –

+0

我更新了答案,你能否看看? :) – Vimvq1987

1

答案很簡單:

爲了將它們合併成一個共同的名單沒有任何共同的數據,利用他們在此的順序,你可以use the Zip method

var rows = reviews 
    .Zip(products, (r, p) => new { Review = r, Product = p }) 
    .Zip(pages, (rp, page) => new { rp.Review, rp.Product, Page = page }); 

這種解決方案的問題是,這些列表必須是相同的長度,否則你的結果將被切成最初的三個列表中的最短列表。

編輯:

如果您不能使用.NET 4中,檢查出Jon Skeet's blog posts on a clean-room implementation of LinqHis article on Zip in particular

如果您使用的.Net 2,然後嘗試他的書房(可能)或try LinqBridge

如何應對不同-lengthed列表

您可以預先墊列表中所需長度。我找不到一個現有的方法來做到這一點,所以我使用的擴展方法:

public static class EnumerableExtensions 
{ 
    public static IEnumerable<T> Pad<T>(this IEnumerable<T> source, 
     int desiredCount, T padWith = default(T)) 
    { 
     // Note: Not using source.Count() to avoid double-enumeration 
     int counter = 0; 
     var enumerator = source.GetEnumerator(); 

     while(counter < desiredCount) 
     { 
      yield return enumerator.MoveNext() 
       ? enumerator.Current 
       : padWith; 
      ++counter; 
     } 
    } 
} 

您可以使用它像這樣:

var paddedReviews = reviews.Pad(desiredLength); 
var paddedProducts = products.Pad(desiredLength, 
    new Product { Value2 = DateTime.Now } 
    ); 

全部編譯樣品和相應的輸出

using System; 
using System.Collections.Generic; 
using System.Linq; 

class Review 
{ 
    public string Value1; 
} 

class Product 
{ 
    public DateTime Value2; 
} 

class Page 
{ 
    public int Value3; 
} 

public static class EnumerableExtensions 
{ 
    public static IEnumerable<T> Pad<T>(this IEnumerable<T> source, 
     int desiredCount, T padWith = default(T)) 
    { 
     int counter = 0; 
     var enumerator = source.GetEnumerator(); 

     while(counter < desiredCount) 
     { 
      yield return enumerator.MoveNext() 
       ? enumerator.Current 
       : padWith; 
      ++counter; 
     } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var reviews = new List<Review> 
     { 
      new Review { Value1 = "123" }, 
      new Review { Value1 = "456" }, 
      new Review { Value1 = "789" }, 
     }; 
     var products = new List<Product>() 
     { 
      new Product { Value2 = DateTime.Now }, 
      new Product { Value2 = DateTime.Now.Subtract(TimeSpan.FromSeconds(5)) }, 
     }; 
     var pages = new List<Page>() 
     { 
      new Page { Value3 = 123 }, 
     }; 

     int maxCount = Math.Max(Math.Max(reviews.Count, products.Count), pages.Count); 

     var rows = reviews.Pad(maxCount) 
      .Zip(products.Pad(maxCount), (r, p) => new { Review = r, Product = p }) 
      .Zip(pages.Pad(maxCount), (rp, page) => new { rp.Review, rp.Product, Page = page }); 

     foreach (var row in rows) 
     { 
      Console.WriteLine("{0} - {1} - {2}" 
       , row.Review != null ? row.Review.Value1 : "(null)" 
       , row.Product != null ? row.Product.Value2.ToString() : "(null)" 
       , row.Page != null ? row.Page.Value3.ToString() : "(null)" 
       ); 
     } 
    } 
} 

123 - 2011/9/7下午10時02分22秒 - 123
456 - 2011/9/7下午10點02分17秒 - (空)
789 - (空) - (空)

上使用的Join標籤

此操作ISN」的邏輯Join。這是因爲你在索引上匹配,而不是每個對象外的任何數據。除了在列表中的位置外,每個對象都必須具有其他數據,這些數據可以在關係數據庫中找到,即Join

+0

如果您在數據庫中嘗試了此操作(沒有作弊並使用行索引),則會返回27行,包括每個列表中值的每種可能組合。這被稱爲「笛卡爾連接」或「笛卡爾產品」。請參閱:http://en.wikipedia.org/wiki/Relational_database#Relational_operations –