根据C#中的条件从List <t>中删除重复项

时间:2016-04-14 22:27:59

标签: c# list

我有一个对象列表(以下代码示例中为exobject),每个对象都有SomeId,AnotherId,SomeOtherId和Timestamp。此列表可能具有重复条目,每条记录具有不同的时间戳。 我希望使用较旧的时间戳删除此对象的所有重复项,并仅保留最新的那些。

示例对象:

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

我需要的清单应该是

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

我在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]);
         }
    }
}

我想知道是否有更优雅和更好的方法来做这个或者如果有一个lambda我可以用它来完成这个。

2 个答案:

答案 0 :(得分:1)

您可以按3个字段进行分组并获取每个组中的第一个:

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

完美运作的示例:

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();

}

答案 1 :(得分:1)

System.Linq有一个Distinct方法。您必须实现IEqualityComparer。详情如何......

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

根据你的评论进行编辑:如果你做了一个订单它应该保留你想要的那个......这里有一些代码...

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;
            }
        }
    }
}