HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Using LINQ or Lambda instead of nested and multiple foreach statements

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
linqstatementsforeachinsteadnestedusingmultipleandlambda

Problem

I want to use a better syntax than nested foreach statements to overwrite the initial list with items from the second list.

In the code below:

  • I want to overwrite initialList with those in secondList that have the same Value (Remove Red).



  • Use the items in secondList where Value was the same (Yellow)



New initialList list should include (Green and Yellow).

static void Main(string[] args)
{
    int useProd = 2;
    int useDomain = 0;

    var person1 = new Person() { prodId = 1, Value = "foo", domainId = 0, Name = "Red" };
    var person2 = new Person() { prodId = 1, Value = "bar", domainId = 0, Name = "Green" };
    var person3 = new Person() { prodId = 1, Value = "foo", domainId = 1, Name = "Yellow" };

    var initialList = new List();
    initialList.Add(person1);
    initialList.Add(person2);

    var secondList = new List();
    secondList.Add(person3);

    List personsToRemove = new List();
    List personsToUpdate = new List();

    foreach (var pers1 in initialList)
    {
        foreach (var pers2 in secondList)
        {
            if (pers1.Value == pers2.Value)
            {
                personsToRemove.Add(pers1);
                personsToUpdate.Add(pers2);
            }
        }
    }
    foreach (var remPers in personsToRemove)
    {
        initialList.Remove(remPers);
    }
    foreach (var updPers in personsToUpdate)
    {
        initialList.Add(updPers);
    }
    foreach (var item in initialList)
    {
        Console.WriteLine(String.Format("Value: {0}, prodId: {1}, domainId: {2}, Name: {3}", item.Value, item.prodId, item.domainId, item.Name));
    }

    Console.ReadKey();
}
public class Person
{
    public int prodId { get; set; }
    public string Value { get; set; }
    public int domainId { get; set; }
    public string Name { get; set; }
}

Solution

By using an IEqualityComparer which only compares the Value property like

public class PersonValueComparer : IEqualityComparer
{
    public bool Equals(Person x, Person y)
    {
        if (x == null && y == null) { return true; }
        if (x == null || y == null) { return false; }

        return x.Value == y.Value;
    }

    public int GetHashCode(Person obj)
    {
        if (obj == null || obj.Value == null) {return 0;}
        return obj.Value.GetHashCode();
    }
}


you can by using linq methods replace the loops by

PersonValueComparer valueComparer = new PersonValueComparer();
        initialList = secondList.Where(p => initialList.Contains(p, valueComparer))
            .Concat(initialList.Where(p => !secondList.Contains(p, valueComparer))).ToList();


We are first using the Where() method to filter the secondList for items which are in the initialList . Then we use Concat() to add the Person''s which are not in thesecondList.

Based on the naming guidelines properties should be named using
PascalCase` casing.

You should always use meaningful and descriptive names for naming methods, variables, properties and classes so Sam the Maintainer sees at first glance what it is about.

Shortening variable names doesn't add any value but instead reduces readability which Sam the Maintainer doesn't like.

Code Snippets

public class PersonValueComparer : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        if (x == null && y == null) { return true; }
        if (x == null || y == null) { return false; }

        return x.Value == y.Value;
    }

    public int GetHashCode(Person obj)
    {
        if (obj == null || obj.Value == null) {return 0;}
        return obj.Value.GetHashCode();
    }
}
PersonValueComparer valueComparer = new PersonValueComparer();
        initialList = secondList.Where(p => initialList.Contains(p, valueComparer))
            .Concat(initialList.Where(p => !secondList.Contains(p, valueComparer))).ToList();

Context

StackExchange Code Review Q#80175, answer score: 11

Revisions (0)

No revisions yet.