【问题标题】:Check IEnumerable<T> for items having duplicate properties检查 IEnumerable<T> 是否有具有重复属性的项目
【发布时间】:2011-01-04 19:19:01
【问题描述】:

如何检查一个 IEnumerable 是否有两个或多个具有相同属性值的项?

例如一个类

public class Item
{
    public int Prop1 {get;set;}
    public string Prop2 {get;set;}
}

然后是IEnumerable&lt;Item&gt;类型的集合

如果Prop1中有重复值的项目,我需要返回false。

【问题讨论】:

    标签: c# linq ienumerable


    【解决方案1】:

    您只想检查 Prop1 对吗?

    怎么样:

    IEnumerable<Item> items = ...
    var noDistinct = items.GroupBy(x => x.Prop1).All(x => x.Count() == 1);
    // it returns true if all items have different Prop1, false otherwise
    

    【讨论】:

    • 而不是noDuplicated,我会使用notDistinct 作为变量名并使用Any 运算符来检查Count 是否大于1。通过使用Any,您不会强迫自己遍历整个可枚举并在第一个匹配Any 子句的情况下退出循环
    • @shirbr510, All 不会强制遍历整个可枚举对象并在第一个 匹配 All 子句的情况下退出循环。与Any 不同,All 为空的可枚举返回 true,这在这种情况下似乎更好。更多关于 AllAny 的信息在这里:stackoverflow.com/a/9027666
    【解决方案2】:

    我认为这种方法会奏效。

    public static bool ContainsDuplicates<T1>(this IEnumerable<T1> source, Func<T1, T2> selector)
    {
        var d = new HashSet<T2>();
        foreach(var t in source)
        {
            if(!d.Add(selector(t)))
            {
                return true;
            }
        }
        return false;
    }
    

    【讨论】:

    • 或者只是if (!d.Add(selector(t))) { return false; }作为循环体。
    • 好电话,这有点快。
    • 这太完美了!只是一个小小的想法。如果集合包含重复,则应返回 true,如果没有重复,则应返回 false :-)
    • @digEmAll 的答案也只遍历一次
    • 方法声明应该是 ContainsDuplicates 否则代码将无法编译。
    【解决方案3】:

    一个简短的、只有一个枚举的解决方案是:

    public static bool ContainsDuplicates<T>(this IEnumerable<T> list)
        => !list.All(new HashSet<T>().Add);
    

    可以读作:一个列表没有重复 All 项目可以 Add-ed到一个集合。

    这在概念上类似于 Jake Pearsons 解决方案;但是,它忽略了投影的独立概念; OP的问题将被解决为:

    items.Select(o => o.Prop1).ContainsDuplicates()
    

    【讨论】:

    • 您上次编辑时格式似乎搞砸了,代码块现在被格式化为纯文本。更重要的是,这导致&lt;T&gt;-tags 被删除,使代码无效。我会自己编辑它,但由于它只是空格,我没有其他要添加的内容,所以我不允许...
    • 谢谢,已修复! (奇怪的错误......我想知道是什么原因造成的;看起来像是某种自动标签转换)
    • @EamonNerbonne n1,另外:Func&lt;IEnumerable&lt;string&gt;, bool&gt; containsDuplicates = list =&gt; !list.All(new HashSet&lt;string&gt;().Add);
    【解决方案4】:

    【讨论】:

    • 这不会告诉他是否有重复值,它只会根据比较器返回不同的值。
    • 只需在两个结果上使用Count() 即可查看是否删除了任何内容...这是暗示的。
    • 有些发帖人可能知道,有些人不知道(从问题来看,OP 可能不是其中之一)。
    【解决方案5】:
    bool x = list.Distinct().SequenceEqual(list);
    

    如果list 有重复项,则xtrue

    【讨论】:

    • 一个漂亮且可读的解决方案,但如果我没记错的话,它会导致list的多个枚举
    【解决方案6】:

    您可以从 IEnumerable 中选择不同的值,然后将计数与完整集合的计数进行比较。

    例子:

    var distinctItemCount = myEnumerable.Select(m => m.Prop1).Distinct().Count();
    
    if(distinctItemCount < myEnumerable.Count())
    {
     return false;
    }
    

    【讨论】:

    • 不起作用。 Distinct 检查是否相等,OP 比较的对象不一定相等。
    • 那么你有机会m =&gt; mm =&gt; m.Prop1
    • 我想我在您发表评论之前更新了我的代码。干杯。
    【解决方案7】:

    这可能是为了提高性能,但这是迄今为止唯一正确的答案。

    // Create an enumeration of the distinct values of Prop1
    var propertyCollection = objectCollection.Select(o => o.Prop1).Distinct();
    
    // If the property collection has the same number of entries as the object
    // collection, then all properties are distinct. Otherwise there are some
    // duplicates.
    return propertyCollection.Count() == objectCollection.Count();
    

    【讨论】:

    • 具有讽刺意味的是,这不是一个正确的答案。提示:Prop1 需要是不同的,而不是 Prop2。
    【解决方案8】:
    public static class EnumerableEx
    {
        public static IEnumerable<T> GetDuplicates<T>(this IEnumerable<T> source)
        {
            return source.GroupBy(t => t).Where(x => x.Count() > 1).Select(x => x.Key);
        }
    }
    

    就个人而言,我喜欢扩展方法的简洁性。 如果您的对象不需要选择器来确定相等性,那么这很好用。

    【讨论】:

      【解决方案9】:

      我们可以通过在ArrayList 中使用.Distinct() 来删除重复条目。

      示例:

      我在 testtable 中有一个 createdby 列,其中包含 5 个重复条目。我只需要得到一行

       ID   Createdby
       ===  ======== 
        1    Reddy
        2    Reddy
        3    Reddy
        4    Reddy
      

      考虑到上表,我只需要选择一个“Reddy”

      DataTable table=new DataTable("MyTable");//Actually I am getting this table data from database
      
      DataColumn col=new DataColumn("Createdby");
      
      var  childrows =  table.AsEnumerable().Select( row => row.Field<object>(col)).Distinct().ToArray();
      

      【讨论】:

        猜你喜欢
        • 2013-12-26
        • 1970-01-01
        • 2014-05-08
        • 1970-01-01
        • 2015-04-27
        • 2017-10-09
        • 2011-06-23
        • 2011-04-07
        • 2018-03-08
        相关资源
        最近更新 更多