Do a correct union on two List<SelectListItem>

4.1k views Asked by At
retval.AddRange(oldList.Union(newList));

Both the oldList and newList are declared here

List<SelectListItem> oldList = new List<SelectListItem>();
List<SelectListItem> newList = new List<SelectListItem>();

I want to union these two lists, removing duplicate items that have the same "text" property. If there is a dupe between newList and oldList on the text property, it should keep the text/value pair of the newList.

The above union doesn't seem to be doing anything besides concat'ing the lists almost, don't know why.

What am I doing wrong?

2

There are 2 answers

6
Reed Copsey On BEST ANSWER

I want to union these two lists, removing duplicate items that have the same "text" property.

The Union method will not handle this requirement. You could do this via:

retVal.AddRange(newList); // Since you want to keep all newList items, do this first

// Add in all oldList items where there isn't a match in new list
retVal.AddRange(oldList.Where(i => !newList.Any(n => i.Text == n.Text)));
1
Jim Mischel On

From reading the documentation it appears that A.Union(B) in effect just adds to A those items from B that aren't already in A. That is:

When the object returned by this method is enumerated, Union enumerates first and second in that order and yields each element that has not already been yielded.

A quick test bears that out. So oldList.Union(newList) will keep the old values whereas newList.Union(oldList) will give you the new values.

Here's my test code:

    class MyThing
    {
        public string Text { get; private set; }
        public int Version { get; private set; }

        public MyThing(string t, int v)
        {
            Text = t;
            Version = v;
        }

        public override int  GetHashCode()
        {
             return Text.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            MyThing other = obj as MyThing;
            if (other == null)
                return false;
            return this.Text.Equals(other.Text);
        }
    }

    static List<MyThing> oldList = new List<MyThing>()
    {
        new MyThing("Foo", 0),
        new MyThing("Bar", 0),
        new MyThing("Fooby", 0),
    };

    static List<MyThing> newList = new List<MyThing>()
    {
        new MyThing("Barby", 1),
        new MyThing("Bar", 1)
    };

    static void DoIt()
    {
        var unionOldNew = oldList.Union(newList);
        Console.WriteLine("oldList.Union(newList)");
        foreach (var t in unionOldNew)
        {
            Console.WriteLine("{0}, {1}", t.Text, t.Version);
        }
        Console.WriteLine();
        var unionNewOld = newList.Union(oldList);
        Console.WriteLine("newList.Union(oldList)");
        foreach (var t in unionNewOld)
        {
            Console.WriteLine("{0}, {1}", t.Text, t.Version);
        }
    }