Giomuti
Giomuti

Reputation: 301

Search, Filter AND Remove a List<List<T>>

I've a problem!

I've a

List <List<Class>> L = new List<List<Class>>();

where Class contains

IDLinea
Posizione

And so on...

I want to have a Distinct List<List<Class>> Where there are no objects with same lines.

For example:

List <List<Class>> L = new List<List<Class>>();

var A = new List<Class>();

Class C = new Class();
C.IDLinea = 1;
C.Posizione = 5;

A.Add(C);

C = new Class();
C.IDLinea = 2;
C.Posizione = 1;

A.Add(C);

L.Add(A);

var B = new List <Class>();

C = new Class();
C.IDLinea = 1;
C.Posizione = 3;

B.Add(C);

C = new Class();
C.IDLinea = 2;
C.Posizione = 1;

B.Add(C);

L.Add(B);

var D = new List <Class>();

C = new Class();
C.IDLinea = 4;
C.Posizione = 1;

D.Add(C);

C = new Class();
C.IDLinea = 2;
C.Posizione = 4;

D.Add(C);

L.Add(D);

So I want A and D

I hope that what I need is clear.

Thanks.

Upvotes: 1

Views: 977

Answers (2)

ShuggyCoUk
ShuggyCoUk

Reputation: 36438

Edited based on your further explanation

enum LineComparisonMode
{
   ///<summary>the order of the line numbers matters, default</summary>
   Ordered = 0, 
   ///<summary>the order of the line numbers doesn't matter
   /// Has a higher cost to the default.
   ///</summary>
   Unordered = 1,
} 

class ListLineComparer : IEqualityComparer<List<Class>>
{
    class LineComparer : IEqualityComparer<Class>
    {
        public bool Equals(Class x, Class y)
        {
            return x.IDLinea == y.IDLinea;
        }

        public int GetHashCode(Class x)
        {
            return x.IDLinea;
        }
    }

    private readonly LineComparer lines;
    private readonly LineComparisonMode mode;

    public ListLineComparer() {}

    public ListLineComparer(LineComparisonMode mode)
    { 
        this.mode = mode;
    }

    public bool Equals(List<Class> x, List<Class> y)
    {
        if (mode == LineComparisonMode.Ordered)
            return x.SequenceEqual(y, lines);
        else
            return x.OrderBy<Class, int>(Line).SequenceEqual(y.OrderBy<Class, int>(Line), lines);
    }

    private static int Line(Class c)
    {
        return c.IDLinea;
    }

    public int GetHashCode(List<Class> x)
    {
        //this is not a good hash (though correct) 
        // but not relevant to current question
        return x.Sum(c => c.IDLinea);
    }
}

// assume List <List<Class>> L = new List<List<Class>>(); from question
var result = L.Distinct(new ListLineComparer()); 

Result in form of IList of IList of Class rather than Lists hopefully that is acceptable. If not you will have the build the lists yourself rather than letting Linq deal with it. If you want to have lines {1,2,3} be considered equal to {3,2,1} then you would need to set the Mode.

var result = L.Distinct(new ListLineComparer(LineComparisonMode.Unordered)); 

This is all a little more verbose that I would have done it myself but makes it clear what is going on/what assumptions are being made so it is simple to change (if say the column position becomes involved later).

Upvotes: 3

Bogdan Gavril MSFT
Bogdan Gavril MSFT

Reputation: 21458

  1. Use a List
  2. Have your class ovveride Equals.
  3. Use the Contains method of the list.

Upvotes: 0

Related Questions