Duha
Duha

Reputation: 829

Linq between two list with condition

I have settings class

public class Setting 
{
    public virtual string Key { get; set; }
    public virtual string Value { get; set; }
}

and i have to list

IEnumerable<Setting> A1 => contain {"A","1"}{"B","2"}
IEnumerable<Setting> A2 => contain {"A","1"}{"B","5"}

i want linq statment to chose the element from list A2 that have same key and different value here is {"B","5"}

I have try

A2.Where(x => A1.Any(y => y.Value != x.Value)).ToList();

this give me the two elemnts in A2

can any one help me thank you


**Edit ** my settings class

 public class Setting : Entity<int>
{
    public virtual DateTime? ModificationDate { get; set; }
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }
    public virtual string Key { get; set; }
    public virtual string Value { get; set; }
    public virtual string ModifiedBy { get; set; }
    public virtual string Type { get; set; }
    public virtual string ValidateRegex { get; set; }    
    public virtual bool IsSystem { get; set; }

}

and i have return from mvc IEnumerable<Setting> let it name settings,

then i get from database the original settings IEnumerable<Setting> let it name dbsettings

i want to know the changed value from settings to make update on it

Upvotes: 2

Views: 5480

Answers (4)

Markus
Markus

Reputation: 22456

You need to compare the Key as well:

A2.Where(x => A1.Any(y => y.Key == x.Key && y.Value != x.Value)).ToList();

The following sample returns { "B", "5" } as the result:

void Main()
{
    var a1 = new List<Setting>(new Setting[] { 
        new Setting() { Key = "A", Value = "1" }, 
        new Setting() { Key = "B", Value = "2" } });
    var a2 = new List<Setting>(new Setting[] { 
        new Setting() { Key = "A", Value = "1" }, 
        new Setting() { Key = "B", Value = "5" } });
    var result = a2.Where(x => a1.Any(y => y.Key == x.Key && y.Value != x.Value)).ToList();
    Console.WriteLine(result);
}

As you are comparing strings, you should be aware that == and != respectively always compares case-sensitive. So the keys need to be written in the same way in both lists (and also differences in case will be recognized as relevant differences). You can also use an overload of string.Compare to specify the comparison options in greater detail.

Upvotes: 6

Tim Schmelter
Tim Schmelter

Reputation: 460108

For performance reasons you could use a lookup:

var a1KeyLookup = A1.ToLookup(x => x.Key);
List<Setting> a2List = A2
    .Where(a2 => a1KeyLookup[a2.Key].Any(a1 => a1.Value != a2.Value))
    .ToList();

Here's your sample data:

IEnumerable<Setting> A1 = new List<Setting> {
    new Setting{Key="A", Value="1"},
    new Setting{Key="B", Value="2"},
};
IEnumerable<Setting> A2 = new List<Setting> {
    new Setting{Key="A", Value="1"},
    new Setting{Key="B", Value="5"},
};

var a1KeyLookup = A1.ToLookup(x => x.Key);
List<Setting> a2List = A2
    .Where(a2 => a1KeyLookup[a2.Key].Any(a1 => a1.Value != a2.Value))
    .ToList();

It returns as expected a list with a single item: Key="B", Value="5"

Upvotes: 2

Mitklantekutli
Mitklantekutli

Reputation: 410

        var A1 = new List<Setting>(){new Setting(){Key = "A", Value = "1"}};
        var A2 = new List<Setting>() { new Setting() { Key = "A", Value = "2" } };
        var a1Keys = A1.Select(x => x.Key).ToList();
        var dupKeys = A2.Where(x => a1Keys.Contains(x.Key)).Select(x=>x.Key);
        var res = A2.Where(x => dupKeys.Contains(x.Key));

Upvotes: 2

dotNET
dotNET

Reputation: 35400

This should do it:

A2.Where(x => A1.Any(y => y.Key == x.Key && y.Value != x.Value))

BTW, your Setting class seems like reinventing the wheel. Dictionary, Tuple and NameValueCollection can all do that for you.

Upvotes: 3

Related Questions