2014-03-27 6 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; 
} 

나는 사전 조회가 매우 빠르고 듣고, 그래서 나는이를 사용하는 이유는 어쩌면 생각,하지만 난 더 나은 방법이 있는지 알고 싶습니다.

감사합니다. 매트 burland, 나는 오타를 수정했습니다.

+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'에 대한 설명 '사전'은 좋을지도 모른다. – 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> 대신 사용할 수 있습니다.