简体   繁体   中英

Distinct rows by their values from sub list LINQ C#

I would like to remove duplicate rows by their values from sub list using LINQ syntax. Below I attached code which does that by different way.

xxxxx xxxxxx xxxxxxx xxxxxxxxxxx xxxxxxxxxxxxxx xxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxxxxxx

List<ZRowCollection> zListCollection = new List<ZRowCollection>();
        zListCollection = zListCollection.OrderBy(p => p.P).ToList();
        int i1 = 1;
        foreach (var item in zListCollection.ToList())
        {
            var subList1 = item.XRowModified.Select(p => p).ToList();
            foreach (var item2 in zListCollection.Skip(i1).ToList())
            {
                var subList2 = item2.XRowModified.Select(p => p).ToList();
                int i = 0;
                foreach (var item3 in subList1)
                {
                    var t2 = subList2.Select(p => p.Average).ToList();
                    decimal average = t2[i];
                    if (item3.Average == average)
                    {
                        i++;
                    }
                    else break;
                }
                if (i == item2.XRowModified.Count)
                {
                    zListCollection.Remove(item2);
                }
            }
            i1++;
        }

properties

class XRowModified
{
    public decimal Id { get; set; }
    public decimal Open { get; set; }
    public decimal High { get; set; }
    public decimal Low { get; set; }
    public decimal Close { get; set; }
    public DateTime Time { get; set; }
    public decimal Average { get; set; }
}
class ZRowCollection
{
    public ZRowCollection()
    {
        this.XRowModified = new HashSet<XRowModified>();
    }
    public int P { get; set; }
    public int High { get; set; }
    public int Low { get; set; }
    public virtual ICollection<XRowModified> XRowModified { get; set; }
}

expected input/output, as a comparer column Average in List<XRowModified>

List<ZRowCollection> zListInput = new List<ZRowCollection>(){
            new ZRowCollection(){P = 0,High = 4,Low = 0, XRowModified = new List<XRowModified>(){
                    new XRowModified(){ Id = 1550, Open = 1.22M,High = 1.24M,Low = 1.21M,Close = 1.23M,Average = 1.225M,
                        Time = new DateTime(2012, 11, 9, 12, 23, 23, 222)},
                    new XRowModified(){ Id = 1551, Open = 1.20M,High = 1.24M,Low = 1.22M,Close = 1.20M,Average = 1.23M,
                        Time = new DateTime(2012, 11, 9, 12, 23, 25, 122)}}},
            new ZRowCollection(){P = 1,High = 3,Low = 0, XRowModified = new List<XRowModified>(){
                    new XRowModified(){ Id = 1555, Open = 1.22M,High = 1.24M,Low = 1.21M,Close = 1.23M,Average = 1.225M,
                        Time = new DateTime(2012, 11, 9, 12, 23, 40, 422)},
                    new XRowModified(){ Id = 1556, Open = 1.20M,High = 1.25M,Low = 1.20M,Close = 1.20M,Average = 1.23M,
                        Time = new DateTime(2012, 11, 9, 12, 23, 46, 522)}}},
            new ZRowCollection(){P = 2,High = 2,Low = 0, XRowModified = new List<XRowModified>(){
                    new XRowModified(){ Id = 1558, Open = 1.22M,High = 1.24M,Low = 1.21M,Close = 1.23M,Average = 1.225M,
                        Time = new DateTime(2012, 11, 9, 12, 30, 11, 622)},
                    new XRowModified(){ Id = 1559, Open = 1.20M,High = 1.24M,Low = 1.22M,Close = 1.20M,Average = 1.23M,
                        Time = new DateTime(2012, 11, 9, 12, 30, 12, 822)}}}
        };
        List<ZRowCollection> zListOutput = new List<ZRowCollection>(){
            new ZRowCollection(){P = 0,High = 4,Low = 0, XRowModified = new List<XRowModified>(){
                    new XRowModified(){ Id = 1550, Open = 1.22M,High = 1.24M,Low = 1.21M,Close = 1.23M,Average = 1.225M,
                        Time = new DateTime(2012, 11, 9, 12, 23, 23, 222)},
                    new XRowModified(){ Id = 1551, Open = 1.20M,High = 1.24M,Low = 1.22M,Close = 1.20M,Average = 1.23M,
                        Time = new DateTime(2012, 11, 9, 12, 23, 25, 122)}}}
        };

In this case I would consider writing a custom equality comparer, which could then be plugged in to the Distinct method. To do this you need two functions Equals and GetHashCode .

Note: It is important the GetHashCode returns the same hash for two equal objects as this is the first thing that Distinct checks.

From what I gather from your code two ZRow 's are equal if their XRow 's have the same sequence of averages, so our equality is that averageSequence1.SequenceEqual(averageSequence2) which would be implemented as so:

public class CustomComparer : IEqualityComparer<ZRowCollection>
{
    public static CustomComparer Instance { get { return new CustomComparer(); } }

    Int32 IEqualityComparer<ZRowCollection>.GetHashCode(ZRowCollection value)
    {
        //One could also use the sum of the averages here, but went for simplicity...
        return value.XRowModified.Count;
    }

    Boolean IEqualityComparer<ZRowCollection>.Equals(ZRowCollection z1, ZRowCollection z2)
    {
        return z1.XRowModified.Select(x => x.Average)
                              .SequenceEqual(z2.XRowModified.Select(x => x.Average));
    }
}

and which would be used like so:

var distinctList = zListCollection.Distinct(CustomComparer.Instance);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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