0

I am having trouble comparing two lists using Linq.
My first list contains object instances, which contain a property of interest, to be compared against a second list that contains only values.
Say we have:

List<uint> referenceValues = new List<uint>(){1, 2, 3};
and
List<SomeObject> myObject= new List<SomeObject>();

Now the SomeObject() class has the property "Value" of type uint.
Note that "myObject" list may contains more elements than the "referenceValues" list and we therefore have to select the appropriate portion of "myObject" to be compared against "referenceValues".

I have found the following stack overflow question, which is related, but not quite what I am after: link

Here is what I have tried so far, but without success:

if (myObject
    .GetRange((int)offset, count)       // Extracted the object of interest from the list
    .Where(x => referenceValues.Equals(x.Value)).Count() == 0)   // Comparing the "Value" properties against the "referenceValues"
{
    // Do something
}

I think I need to use "SequenceEqual" somehow, but I am not really getting how to.
Any advice would be very welcome.

EDIT

Reproducible example:

using System;
using System.Linq;
using System.Collections.Generic;
                    
public class Program
{
    public static void Main()
    {
        int offset = 0;
            
        List<uint> referenceValues = new List<uint>(){1, 2, 3};

        List<SomeObject> myObject= new List<SomeObject>(){new SomeObject(){Value=1}, 
                                                          new SomeObject(){Value=2},
                                                          new SomeObject(){Value=3}};
        
        if (myObject
            .GetRange(offset, referenceValues.Count()-1)       // Extracted the object of interest from the list
            .Where(x => referenceValues.Equals(x.Value)).Count() == referenceValues.Count())   // Comparing the "Value" properties against the "referenceValues"
        {
            // Do something
            Console.WriteLine("Lists are matching!");
        }
        else
        {
            Console.WriteLine("Lists are not matching!");
        }
    }
}

public class SomeObject
{
    public uint Value = 0;
}

EDIT2

Working solution as per suggestion from Guru Stron:

using System;
using System.Linq;
using System.Collections.Generic;
                    
public class Program
{
    public static void Main()
    {
        int offset = 0;
            
        List<uint> referenceValues = new List<uint>(){1, 2, 3};

        List<SomeObject> myObject= new List<SomeObject>(){new SomeObject(){Value=1}, 
                                                          new SomeObject(){Value=2},
                                                          new SomeObject(){Value=3}};
        
        if (myObject.
            GetRange((int)offset, referenceValues.Count())   
            .Select(someObject => someObject.Value)
            .SequenceEqual(referenceValues))
        {
            // Do something
            Console.WriteLine("Lists are matching!");
        }
        else
        {
            Console.WriteLine("Lists are not matching!");
        }
    }
}

public class SomeObject
{
    public uint Value = 0;
}

Recommended book about Linq expressions: LINQ Pocket Reference

2
  • If myObject is a List<SomeObject> then myObject.SomeObject is not going to compile. Commented Oct 21, 2020 at 15:09
  • Thanks, I just saw that as I created a simple reproducible example on the Code Fiddler :-) Commented Oct 21, 2020 at 15:15

2 Answers 2

1

If you want to check if some subset of myObject values has some concrete order by some property you can do something like this:

bool inOrder = myObject
    .GetRange((int)offset, count)   
    .Select(someObject => someObject.Value)
    .SequenceEqual(referenceValues);

If you want to just check that all values are present in the specified referenceValues you can use All (also if source range is empty this returns true):

bool allPresent = myObject
    .GetRange((int)offset, count)   
    .All(someObject => referenceValues.Contains(someObject.Value));

For full collection match without ordering I don't know out of box solution but you can look for one for example here.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks a lot, I think this is working :-) Do you have a good tutorial about LINQ to recommend? I am always struggling with that.
But the second option will not care about order?
@stackMeUp was glad to help. You can look here for some recommendations. When I was starting using LINQ LINQ Pocket Reference by Albahari proved to be useful for me.
@stackMeUp second one will not, it will just check that all values in the collection exist in referenceValues (but not vice versa, there maybe missing entries from referenceValues in myObject.Range).
@stackMeUp again - was glad to help. Read the reviews first, maybe it will not be as useful for you as it was for me. People are different)
|
0
if(myObject.Any(x => referenceValues.Contains(x.Value)) {}

I ignored the GetRange part but should make no difference.

4 Comments

That would not preserve the order I believe?
I presumably missinterpreted you question. You wanted to find all values of referenceValues in the correct order. Not just if there is an intersection?
Correct, Guru Stron's solution seems to work, thanks :-)
Will do, still going through it :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.