使用字典来检查列表中的唯一元素是常见的做法吗?



假设我有一个对象列表,对象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;
}

我听说字典查找非常快,所以我想这可能就是为什么要使用这个,但是我想知道是否有更好的方法。

谢谢matt burland,我改正了错字。(还不能评论)

您可以使用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>是专门为该目的设计的。

字典强制代码确保它只包含唯一的键,而不是值。所以如果你尝试添加另一个已经存在的键,它会抛出一个错误。当你想要获取一个值时,你只需要通过键名来获取它,字典会使用散列进行查找,这使得它非常非常快。当你想要搜索列表时,你必须遍历整个列表来找到你想要的那个,这可能很慢,因为你要遍历整个列表。

更短的方式是:

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

尽管这可能不会保留Basket中给定名称的第一项

因此,如果名称是对象的唯一部分(即键),并且项目的顺序并不重要,那么Dictionary<string, Fruit>是存储它们的完全有效的方法。另一个选择是HashSet,但是你需要在你的Fruit类中实现EqualsGetHashCode(或创建IEqualityComparer<Fruit>)。

但是对于你的特定代码,你可以使用Linq语句(像Lee的),这是有效的,但是对于你的特定代码,你不需要在创建字典的同时创建一个唯一项的列表(除非顺序很重要),因为你可以返回tempUniqueFruits.Values.ToList()

另外,如果您想构建唯一项的列表(以保持顺序),那么由于您实际上不使用字典中的值,而只是使用键,因此您可以使用HashSet<string>代替。

相关内容

  • 没有找到相关文章

最新更新