2014-03-27 33 views
0

說我有一個對象列表,對象Fruit。水果有一個屬性Name。即Fruit1.Name = "Apple"Fruit2.Name = "Orange"Fruit3.Name = "Apple"Fruit4.Name = "Melon" ...等使用字典檢查列表中的唯一元素是否常見?

List<Fruit> Basket = {Fruit1, Fruit2, Fruit3, Fruit4, Fruit 5...... Fruit 100}. 

我想擁有獨特的水果,其中列表中的每一個水果都有其獨特的名字的列表。我想優化時間。 我見過一些人做了以下事情。這是最好的方式嗎?

public List<Fruit> GetUniqueFruits(List<Fruit> Basket) 
{ 
    Dictionary<string, Fruit> tempUniqueFruits = new Dictionary<string, Fruit>(); 
    List<Fruit> uniqueFruits = new List<Fruit>(); 
    foreach(var fruit in Basket) 
    { 
     if (!tempUniqueFruits.ContainsKey(fruit.Name) 
     { 
      tempUniqueFruits.Add(fruit.Name, fruit); 
      uniqueFruits.Add(fruit); 
     } 
    } 
    return uniqueFruits; 
} 

我聽說字典查找速度非常快,所以我想也許這就是爲什麼使用它,但我想知道是否有更好的方法。

謝謝馬特布蘭德,我修正了錯字。 (coulnd't comment yet)

+1

那麼這行是錯誤的開始:'字典<字符串,水果> tempUniqueFruits =新字典();' –

回答

2

您可以使用IEqualityComparer來澄清代碼。

public List<Fruit> GetUniqueFruits(List<Fruit> Basket) { 
    var set = new HashSet<Fruit>(Basket, new FruitNameEqualityComparer()); 
    return set.ToList(); 
} 

public class Fruit { 
    public string Name { get; set; } 
    public DateTime RipeTime { get; set; } 
} 

class FruitNameEqualityComparer : IEqualityComparer<Fruit> { 
    public int Compare(Fruit a, Fruit b) { 
     return a.Name.CompareTo(b.Name); 
    } 

    public bool Equals(Fruit a, Fruit b) { 
     return a.Name.Equals(b.Name); 
    } 

    public int GetHashCode(Fruit f) { 
     return f.Name.GetHashCode(); 
    } 
} 

Dictionary<T, U>當您從鍵映射到值最好是使用,但如果你只維持一組唯一值沒有任何映射感興趣,一個HashSet<T>是專門爲這個目的而設計的。

+0

我同意,集應該通常用於唯一性,但解釋爲什麼'HashSet'而不是'Dictionary'可能很好 – Sam

1

字典強制代碼確保它只包含唯一鍵,而不是值。所以如果你嘗試添加另一個已經存在的密鑰,它將會拋出一個錯誤。當想要獲取一個值時,你只需要通過字典使用散列進行查找的關鍵名稱來獲取它,這使得它非常快速。當想要搜索列表時,必須遍歷整個列表以找到您想要的列表,因爲您正在遍歷整個列表,因此可能會很慢。

1

更短的方法是:

return Basket.GroupBy(f => f.Name).Select(grp => grp.First()).ToList(); 

雖然這可能不是給定名稱保持Basket的第一個項目。

1

因此,如果名稱是對象的唯一部分(即鍵),並且項目的順序並不重要,那麼Dictionary<string, Fruit>是存儲它們的完全有效方式。另一種選擇是HashSet,但您需要在Fruit類中實現EqualsGetHashCode(或創建IEqualityComparer<Fruit>)。

但是,對於您特定的代碼,您可以使用的Linq語句(如Lee的語句)效率很高,但使用您的特定代碼,您不需要同時創建一個獨特項目列表正在構建您的字典(除非訂單是重要的),因爲您可以返回tempUniqueFruits.Values.ToList()

另外,如果您要構建唯一項目列表(以保留順序),那麼因爲您實際上並未使用字典,只是鍵,你可以用HashSet<string>代替。

相關問題