简体   繁体   English

从列表中删除重复项 <T> 基于C#中的条件

[英]Remove duplicates from a List<T> based on a condition in C#

I have a List of an object (exobject in the below code sample) who each have SomeId, AnotherId, SomeOtherId and Timestamp. 我有一个对象的列表(在下面的代码示例中为exobject),每个对象都有SomeId,AnotherId,SomeOtherId和Timestamp。 This list might have duplicate entries with each record having a different Timestamp. 此列表可能有重复的条目,每个记录的时间戳都不同。 I want to remove all duplicates of this object with older Timestamps and only keep those that are the latest. 我想删除带有较旧时间戳的该对象的所有重复项,而仅保留最新的那些。

Sample object: 样本对象:

SomeId    AnotherId    SomeOtherId    Timestamp
1         2            1              10
1         2            1              20
1         3            2              30
2         3            4              40
1         3            2              50

My required list should be 我需要的清单应该是

1,2,1,20 and 1,3,2,50 and 2,3,4,40.

I have a very crude implementation in C# do do this. 我在C#中有一个非常粗糙的实现来做到这一点。

for (int i = 0; i < exObject.Count - 1; i++)
{
    for (int j = i + 1; j < exObject.Count - 1; j++)
    {
        if (exObject[i].SomeId == exObject[j].SomeId && exObject[i].AnotherId == exObject[j].AnotherId && exObject[i].SomeOtherId == exObject[j].SomeOtherId)
         {
             if (exObject[i].TimeStamp < exObject[j].TimeStamp)
                 exObject[i].TimeStamp = exObject[j].TimeStamp;
             exObject.Remove(exObject[j]);
         }
    }
}

I would like to know if there is a more elegant and nicer way to do this or if there is a lambda I can use to accomplish this. 我想知道是否有更优雅,更好的方法来执行此操作,或者是否可以使用lambda来完成此操作。

You can Group By the 3 fields and take the first one of each group: 您可以按3个字段分组并采用每个分组的第一个:

List
  .GroupBy(x=> new {x.prop1, x.prop2, x.prop3 })
  .Select(g=> g.OrderByDescending(o=> o.dateprop).First())
  .ToList();

Sample that is working perfectly: 运行良好的示例:

static void Main(string[] args)
{
    List<Foo> myList = new List<Foo>();
    myList.Add(new Foo(1, 2, 1, 10));
    myList.Add(new Foo(1, 2, 1, 20));
    myList.Add(new Foo(1, 3, 2, 30));
    myList.Add(new Foo(2, 3, 4, 40));
    myList.Add(new Foo(1, 3, 2, 50));

    // The following returns 3 results with 20, 50 and 40 timeStamps.

    var results = myList.GroupBy(x => new { x.SomeId, x.AnotherId, x.SomeOtherId })
                            .Select(g => g.OrderByDescending(o => o.Timestamp).First()).ToList();

}

System.Linq has a Distinct method. System.Linq有一个Distinct方法。 You'd have to implement an IEqualityComparer. 您必须实现IEqualityComparer。 Details of how here... 详细说明...

https://msdn.microsoft.com/en-us/library/bb338049(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/bb338049(v=vs.110).aspx


Edit based on your comment: If you do an orderBy it should keep the one you want... here's some code... 根据您的评论进行编辑:如果您执行了一项订单,它应该保留您想要的订单...这是一些代码...

using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var data = new[]
            {
                new SomeClass { SomeId = 1, AnotherId = 1, SomeOtherId = 1, Timestamp = 10 },
                new SomeClass { SomeId = 1, AnotherId = 1, SomeOtherId = 1, Timestamp = 20 }, // Duplicate
                new SomeClass { SomeId = 1, AnotherId = 2, SomeOtherId = 2, Timestamp = 30 },
                new SomeClass { SomeId = 1, AnotherId = 2, SomeOtherId = 2, Timestamp = 35 }, // Duplicate
                new SomeClass { SomeId = 2, AnotherId = 4, SomeOtherId = 4, Timestamp = 40 },
                new SomeClass { SomeId = 3, AnotherId = 2, SomeOtherId = 2, Timestamp = 50 },
                new SomeClass { SomeId = 1, AnotherId = 1, SomeOtherId = 1, Timestamp = 50 } // Duplicate
            };

            var distinctList = data
                        .OrderBy(x => x.Timestamp)
                        .Distinct(new SomeClassComparer())
                        .ToList();
            }

        public class SomeClass
        {
            public int SomeId { get; set; }
            public int AnotherId { get; set; }
            public int SomeOtherId { get; set; }
            public int Timestamp { get; set; }
        }

        public class SomeClassComparer : IEqualityComparer<SomeClass>
        {
            public bool Equals(SomeClass x, SomeClass y)
            {
                if (ReferenceEquals(x, y))
                {
                    return true;
                }

                //Check whether any of the compared objects is null.
                if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
                {
                    return false;
                }

                //Check whether the SomeClass's properties are equal.
                return x.SomeId == y.SomeId &&
                       x.AnotherId == y.AnotherId &&
                       x.SomeOtherId == y.SomeOtherId;
            }

            public int GetHashCode(SomeClass someClass)
            {
                //Check whether the object is null
                if (ReferenceEquals(someClass, null))
                {
                    return 0;
                }

                //Get hash code for the fields
                var hashSomeId = someClass.SomeId.GetHashCode();
                var hashAnotherId = someClass.AnotherId.GetHashCode();
                var hashSomeOtherId = someClass.SomeOtherId.GetHashCode();

                //Calculate the hash code for the SomeClass.
                return (hashSomeId ^ hashAnotherId) ^ hashSomeOtherId;
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM