Share via


Compare two List(T) via three or multiple properties using LINQ in C#

Question

Friday, September 4, 2015 3:46 AM

I have a List(T) like this one:

public class matrix
{
    public string Row { get; set; }
     public string Column { get; set; }
      public int Value { get; set; }
 }

In my main class, I have declared matrixList1 and matrixList2 simultaneously:

List<matrix> matrixList1 = new List<matrix>(list1.Count + list2.Count + matrix1.Length);

List<matrix> matrixList2 = new List<matrix>(list2.Count + list2.Count + matrix2.Length);

Now i want to compare those list using LINQ based on the three properties called Row, Column and Value...But i got error each time, my code is given below:

var matchedItem = from values1 in matrixList1
              join values2 in matrixList2
              on (values1.Row equals values2.Row) && (values1.Column equals values2.Column) && (values1.Value equals values2.Value)
              select new { values1, values2 };

How could i solve this problem? Please help me out regarding this. Thank you in advance.

All replies (6)

Friday, September 4, 2015 4:16 AM | 2 votes

How about this?

var matrix1 = new [] { new Matrix { Row = "0", Column = "0", Value = 1 } };
var matrix2 = new [] { new Matrix { Row = "0", Column = "0", Value = 1 } };

matrix1.Where(x => matrix2.Any(y => x.Row == y.Row && x.Column == y.Column && x.Value == y.Value));

That's going to select all the Matrix 1 objects that matches any of the Matrix 2 Columns, Rows and Values.

You could also do this:

var result = from outer in matrix1
             from inner in matrix2
             where outer.Row == inner.Row && outer.Column == inner.Column && outer.Value == inner.Value
             select outer;

You can only use one condition with join, so doing multiple ANDs in this case will not work.

Mark good replies as helpful and correct ones as answers! - http://blog.filipekberg.se
Check out my recently published book C# Smorgasbord on Amazon


Friday, September 4, 2015 12:56 PM

great!!! I have tried the method of 2nd one. It gives me the correct answer. Thank you so much. 


Friday, September 4, 2015 1:45 PM | 1 vote

You also can use Contains or  Intersect methods:

 class Program
    {
        static void Main(string[] args)
        {
            List<matrix> matrixList1 = new List<matrix>();
            List<matrix> matrixList2 = new List<matrix>();
            matrixList1.Add(new matrix { Row = "0", Column = "0", Value = 1 });
            matrixList2.Add(new matrix { Row = "0", Column = "0", Value = 1 });

            var result1 = matrixList1.Where(c => matrixList2.Contains(c));
            Console.WriteLine(result1.Count());
            Console.ReadLine();

            var result2 = matrixList1.Intersect(matrixList2, new MatrixComparer());
            Console.WriteLine(result2.Count());
            Console.ReadLine();
        }

        class MatrixComparer: IEqualityComparer<matrix>
        { 
            public bool Equals(matrix x, matrix y)
            {
                if (Object.ReferenceEquals(x, y)) return true;
                if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                    return false;

                return x.Row == y.Row && x.Column == y.Column && x.Value == y.Value;
            }

            public int GetHashCode(matrix obj)
            {
                if (Object.ReferenceEquals(obj, null)) return 0;
                int hashRow = obj.Row == null ? 0 : obj.Row.GetHashCode();
                int hashColumn = obj.Column == null ? 0 : obj.Column.GetHashCode();
                return obj.Value ^ hashRow ^ hashColumn;
            }
        }

        public class matrix : IEquatable<matrix>
        {
            public string Row { get; set; }
            public string Column { get; set; }
            public int Value { get; set; }

            public bool Equals(matrix other)
            {
                return this.Row == other.Row && this.Column == other.Column && this.Value == other.Value;
            }         
          
        }
    }

Friday, September 4, 2015 8:19 PM

Thank you so much. It is very helpful for me. 

Could you please help me to find the non-matched values from that two list 'matrixlist1' and 'matrixlist2' where (matrixlist1.Row != matrixlist2.Row && matrixlist1.Column != matrixlist2.Column && matrixlist1.Value != matrixList2.value)?

I have tried so many times but its not working. every time i get error message. Please help me!!!

Thank you in advance.

Saima Sultana


Saturday, September 5, 2015 8:40 AM

Why use linq to access those properties? Just implement a proper comparsion logic into matrix.

You are doing a simple value equality check:

Comparing Values for Equality in .NET: Identity and Equivalence - CodeProject

Every class should just bring that kind of code along on it's own. Indeed it already does bring fitting referene equality code along (inherits that from object).

It is a bit odd for a class to use value type semantic for comparision, but it is not unheard of (string is one of the few classes that has it too). Still this pattern is more often used with value types/structures then classes.
Are you certain matrix would not be better implemented as a structure? Is matrix suppsed to be inmutable like string (http://stackoverflow.com/questions/3729873/problem-with-struct-and-property-in-c-sharp)?


Saturday, September 5, 2015 8:50 AM

Just change this code

var result1 = matrixList1.Where(c => matrixList2.Contains(c));
            Console.WriteLine(result1.Count());
            Console.ReadLine();

            var result2 = matrixList1.Intersect(matrixList2, new MatrixComparer());
            Console.WriteLine(result2.Count());
            Console.ReadLine();

to

var result1 = matrixList1.Where(c => !matrixList2.Contains(c));
            Console.WriteLine(result1.Count());
            Console.ReadLine();

            var result2 = matrixList1.Except(matrixList2, new MatrixComparer());
            Console.WriteLine(result2.Count());
            Console.ReadLine();