【问题标题】:Best way to find out distinct item in the big list在大列表中找出不同项目的最佳方法
【发布时间】:2013-07-23 14:08:59
【问题描述】:

我有一个以下集合,其中包含超过 500000 个项目。

List<Item> MyCollection = new List<Item>();

然后输入:

class Item
{
   public string Name { get; set; }
   public string Description { get; set; }
}

我想返回具有不同名称的项目列表。即根据名称找出不同的项目。

有哪些可能的方法以及哪种方法在时间和记忆方面最好。虽然两者都很重要,但时间越少,记忆就越重要。

【问题讨论】:

标签: c# .net list c#-4.0 collections


【解决方案1】:

您可以对列表进行排序,然后删除所有重复的项目,但似乎将所有数据存储在 Dictionary&lt;string, string&gt; 中对于这项任务会更好。或者甚至可以将所有列表放入HashSet

【讨论】:

  • @lazyberezovsky 为什么不呢?类项包含两个字符串字段。 Name 可能是键,Description 是值,正好适合这种情况
  • 实际上不同的项目有问题。因此我认为你有几个同名的项目,适当的类型是Dictionary&lt;string, List&lt;Item&gt;&gt;(或查找)。但是如果答案解决了问题,那当然是正确的+1
【解决方案2】:

第一个解决方案:

public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> keySelector)
{
    var alreadyUsed = new HashSet<TKey>();            
    foreach (var item in sequence)
    {
        var key = keySelector(item);
        if (alreadyUsed.Add(key))
        {
            yield return item;
        }
    }
}

第二种是使用.Distinct() 并在您的项目中覆盖Equals 以匹配名称

【讨论】:

    【解决方案3】:

    我会选择 Linq,除非或直到性能不足:

    var considered = from i in MyCollection
             group i by i.Name into g
             select new { Name = g.Key, Cnt = g.Count(), Instance = g.First() };
    var result = from c in considered where c.Cnt == 1 select c.Instance;
    

    (假设我已将您的问题正确解释为“返回那些Name 仅在列表中出现一次的项目”)

    【讨论】:

    • 我是这样解释问题的,但有点不清楚!
    【解决方案4】:

    MoreLinq 有一个 DistinctBy 扩展,非常适合这类事情,它的开源和几行代码很容易添加到您的代码中。

    var results = MyCollection.DistinctBy(p => p.Name);
    

    【讨论】:

      【解决方案5】:

      我有java版本的代码

      implement the comparator then define the method as below in Item class
      
      public int compare(MyObject o1, MyObject o2)
      {
         // return 0 if objects are equal in terms of your data members such as name or any
      }
      

      然后在定义 MyCollection 的类中使用下面的代码

         HashSet<Item> set1 = new HashSet<Item>();
         set1.addAll(MyCollection);
         MyCollection.clear();
         MyCollection.addAll(set1);
      

      这将为您提供排序集

      【讨论】:

        【解决方案6】:

        我可以看到您找到了答案,但您也可以使用 Distinct 相当简单地做到这一点;

        internal class NameComparer : IEqualityComparer<Item> {
            public bool Equals(Item x, Item y) { return x.Name == y.Name;     }
            public int GetHashCode(Item obj) { return obj.Name.GetHashCode(); }
        }
        
        var distinctItems = MyCollection.Distinct(new NameComparer());
        

        【讨论】:

          猜你喜欢
          • 2016-12-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-08
          • 2013-11-26
          • 1970-01-01
          • 2011-01-05
          • 1970-01-01
          相关资源
          最近更新 更多