2013-04-19 41 views
3

我已經瀏覽了本網站上的問題,但沒有找到與我的特定問題匹配的問題。我怎樣才能從另一個可枚舉的c上插入一個枚舉#

假設我有以下幾點:

Product[] store1 = { new Product { Name = "apple", Code = 9, Code1="1" }, 
        new Product { Name = "orange", Code = 4 } }; 

Product[] store2 = { new Product { Name = "apple", Code = 9, Code2="2" }, 
        new Product { Name = "lemon", Code = 12 } }; 

有了:

public class Product : IEquatable<Product> 
{ 
    public string Name { get; set; } 
    public int Code { get; set; } 
    public string Code1 { get; set; } 
    public string Code2 { get; set; } 

    public bool Equals(Product other) 
    { 

     //Check whether the compared object is null. 
     if (Object.ReferenceEquals(other, null)) return false; 

     //Check whether the compared object references the same data. 
     if (Object.ReferenceEquals(this, other)) return true; 

     //Check whether the products' properties are equal. 
     return Code.Equals(other.Code) && Name.Equals(other.Name); 
    } 

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects. 

    public override int GetHashCode() 
    { 

     //Get hash code for the Name field if it is not null. 
     int hashProductName = Name == null ? 0 : Name.GetHashCode(); 

     //Get hash code for the Code field. 
     int hashProductCode = Code.GetHashCode(); 

     //Calculate the hash code for the product. 
     return hashProductName^hashProductCode; 
    } 
} 

我怎樣才能返回一個可枚舉的數據從商店1從商店2上匹配的數據覆蓋,從剛插入將store2存儲到不匹配的store1中。基本上我正在尋找C#等價於TSQL Merge語句。

在這一天結束時運行以下命令:

foreach (var product in union) 
     Console.WriteLine(product.Name + " " + product.Code + " " + product.Code1 + " " + product.Code2); 

我想回去:

蘋果9 1 2

橙4

檸檬12

但是,當我運行這個:

IEnumerable<Product> union = store1.Union(store2); 

我得到:

蘋果9 1

橙4

檸檬12

,當我運行此:

IEnumerable<Product> union = store1.Concat(store2); 

我得到:

蘋果9 1

橙4

蘋果9 2

檸檬12

在此先感謝您的幫助。

+0

什麼是你想覆蓋數據的關鍵值? –

+0

這只是從MSDN上的[文章](http://msdn.microsoft.com/en-us/library/bb358407.aspx)中摘錄的一個示例,但如果我在現實生活中使用此示例,那麼id就像匹配名稱和代碼,然後覆蓋code1和code2,如果它們在store1中爲空。 – DrRocket

+0

@ user1031517當你有'{Name =「apple」,Code = 9,Code1 =「1」}和'{Name =「apple」,Code = 9,Code1 =「2」,Code2 =「2 「}',在這種情況下應該考慮?這裏'Code1'屬性在兩個項目中都有重疊。當我們在這兩個系列中有許多這樣的重疊產品時會發生什麼?這些都應該被考慮?像'{Name =「apple」,Code = 9,Code1 =「1」}和'{Name =「apple」,Code = 9,Code2 =「2」}'的情況會出現在同一個集合中,例如,在'store1'中? – nawfal

回答

0
 // 
     // Summary: 
     //  Produces the set union of two sequences by using the default equality comparer. 
     // 
     // Parameters: 
     // first: 
     //  An System.Collections.Generic.IEnumerable<T> whose distinct elements form 
     //  the first set for the union. 
     // 
     // second: 
     //  An System.Collections.Generic.IEnumerable<T> whose distinct elements form 
     //  the second set for the union. 
     // 
     // Type parameters: 
     // TSource: 
     //  The type of the elements of the input sequences. 
     // 
     // Returns: 
     //  An System.Collections.Generic.IEnumerable<T> that contains the elements from 
     //  both input sequences, excluding duplicates. 
     // 
     // Exceptions: 
     // System.ArgumentNullException: 
     //  first or second is null. 
public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second); 

對於該函數

不重複的原因。

所以你必須寫你的工會功能的產品[]

public static class ProductExtension 
{ 
    public static IEnumerable<T> Union<T>(this IEnumerable<T> store1, IEnumerable<T> store2) 
    { 
     List<T> List = new List<T>(); 
     foreach (var item in store2) 
     { 
      if (store1.Any(n=>n.Equals(item))) 
      { 
       var obj = store1.First(n => n.Equals(item)); 
       foreach (System.Reflection.PropertyInfo pi in obj.GetType().GetProperties()) 
       { 
        object v1 = pi.GetValue(obj, null); 
        object v2 = pi.GetValue(item, null); 
        var value = v1; 
        if (v2 != null && (v1 == null || v1.ToString() == string.Empty) && v1 != v2) 
        { 
         value = v2; 
        } 
        pi.SetValue(obj, value, null); 
       } 
       List.Add(obj); 
      } 
      else { 
       List.Add(item); 
      }    
     } 

     foreach (var item in store1) { 
      if(!store2.Any(n=>n.Equals(item))){ 
       List.Add(item); 
      } 
     } 
     return List.AsEnumerable(); 
    } 
} 
0

而不是依賴於反思,我會寫我自己爲它的功能在Product類。就像一個AsComboCombineWith方法:

public IEnumerable<Product> AsCombo(Product p) 
{ 
    //if not equal, return both 
    if (!Equals(p)) 
    { 
     yield return this; 
     yield return p; 
     yield break; 
    } 

    //if equal return the one desired by checking all properties 
    yield return new Product //always better to return new instance for linq queries 
    { 
     Name = Name, 
     Code = Code, 
     Code1 = Code1 ?? p.Code1, //I give preference to 'this' 
     Code2 = Code2 ?? p.Code2 //I give preference to 'this' 
    }; 
} 

現在所有的標準LINQ查詢應該工作。

var combo = store1.Concat(store2) 
        .GroupBy(x => x) 
        .Where(x => x.Count() == 1) 
        .Select(x => x.Key) //get non duplicated products 
        .Concat(store1.Distinct() //concat them with combined form of duplicated products 
           .Join(store2.Distinct(), x => x, x => x, (x, y) => x.AsCombo(y)) 
           .SelectMany(x => x)) 
        .ToList(); 

這是一個與下面的查詢更容易一些,但那麼真實依靠實施Union(假設Union保持第一或外序列的副本,並從隨後的/內序列丟棄重複)。不建議。

var combo = store1.Join(store2, x => x, x => x, (x, y) => x.AsCombo(y)) 
        .SelectMany(x => x) 
        .Union(store1) 
        .Union(store2) 
        .ToList(); 
相關問題