2010-11-07 15 views
1

問題:如何簡化下面的代碼,因爲我正瞄準thing類中的30個不同屬性。Linq中的多列

代碼查找'thing'屬性的唯一性。

public class thing 
{ 
    public string Name { get; set; } 
    public string Colour { get; set; } 
    public string Position { get; set; } 
    public string Height { get; set; } 
} 

public List<thing> SeeIfAnyInListHaveAUniqueSingleColumn(List<thing> listOfThings) 
    { 
     // try colour 
     IEnumerable<IGrouping<string, thing>> thingQuery2 = from t in listOfThings 
                  group t by t.Colour; 
     List<thing> listOfThingsFound = new List<thing>(); 
     foreach (var thingGroup in thingQuery2) 
     { 
      if (thingGroup.Count() == 1) 
      { 
       foreach (thing thing in thingGroup) // there is only going to be 1 
        listOfThingsFound.Add(thing); 
      } 
     } 

     // try position 
     IEnumerable<IGrouping<string, thing>> thingQuery3 = from t in listOfThings 
                  group t by t.Position; 

     foreach (var thingGroup in thingQuery3) 
     { 
      if (thingGroup.Count() == 1) 
      { 
       foreach (thing thing in thingGroup) // there is only going to be 1 
        listOfThingsFound.Add(thing); 
      } 
     } 
     return listOfThingsFound; 
    } 

http://www.programgood.net/2010/11/06/FindingUniquenessInData.aspx

+1

是所有屬性字符串嗎? – 2010-11-07 22:10:21

+0

你想知道任何財產是不同的?或者你是否總是在代碼中知道你正在檢查的財產? – JeremyWeir 2010-11-08 00:00:38

+0

亨克 - 好問題!是的,所有屬性都是字符串。 – 2010-11-08 00:30:31

回答

1

我認爲,如果你抽象掉FindUnique操作,就可以更輕鬆地編寫測試:

static IEnumerable<T> FindDistinct<T, TKey>(this IEnumerable<T> source, 
              Func<T, TKey> keySelector) 
{ 
    return from item in source 
      group item by keySelector(item) into grp 
      where grp.Count() == 1 
      from single in grp 
      select single; 
} 

然後,你可以寫:

var thingsWithUniqueName = listOfThings.FindDistinct(t => t.Name); 
var thingsWithUniquePosition = listOfThings.FindDistinct(t => t.Position); 
var thingsWithUniqueHeight = listOfThings.FindDistinct(t => t.Height); 
+0

非常感謝Gabe(和Dabblernl和Enigmativity) – 2010-11-08 00:43:02

0

下載代碼你想編寫的代碼,如:

foreach var property in Thing.Properties 
{ 
    IEnumerable<IGrouping<string, thing>> thingQuery2 = from t in listOfThings  
                 group t by t.property;  
    List<thing> listOfThingsFound = new List<thing>();  
    foreach (var thingGroup in thingQuery2)  
    {  
     if (thingGroup.Count() == 1)  
     {  
      foreach (thing thing in thingGroup) // there is only going to be 1  
       listOfThingsFound.Add(thing);  
     }  
    } 
    ... 
} 

你只能做到這一點通過反射,這是你應該遠離。我能想到的唯一的事情就是將這些屬性存儲在某種集合中,如字典,並且迭代

0

我只注意到加布提供了我即將發佈的同樣的答案。無論如何,我認爲我會發布這一點,以強化這個答案是LINQ的一個很好的使用。 請接受Gabe的回答,而不是這個。做得好的Gabe!

public static IEnumerable<T> WhereUniqueByKey<T, P>(
    this IEnumerable<T> @this, Func<T, P> keySelector) 
{ 
    return @this 
     .GroupBy(keySelector) 
     .Where(gt => gt.Count() == 1) 
     .SelectMany(gt => gt, (_, t) => t); 
} 

根據Gabe的回答,我的函數是一個擴展方法,它需要在靜態類中定義。我們的答案之間唯一真正的區別是Gabe使用了LINQ查詢語法,並且我使用了直接的LINQ方法調用。結果相同,用法也一樣:

var thingsWithUniqueName = listOfThings.WhereUniqueByKey(t => t.Name); 
var thingsWithUniquePosition = listOfThings.WhereUniqueByKey(t => t.Position); 
var thingsWithUniqueHeight = listOfThings.WhereUniqueByKey(t => t.Height); 
+0

哈!我原本打算髮布流利的版本,並在最後一刻決定使用查詢理解語法。 – Gabe 2010-11-07 23:53:05