frictionlesspulley
frictionlesspulley

Reputation: 12368

Merge Complex Object List using Union / Intersect

Consider two lists of complex objects say :

        var first = new List<Record>
            {
                new Record(1, new List<int> { 2, 3 }),
                new Record(4, new List<int> { 5, 6 })
            };

        var second = new List<Record>
            {
                new Record(1, new List<int> { 4 })
            };

where a Record is defined as below. Nothing fancy, just a class with Id and list of SecondaryIdentifiers.

    public class Record
    {
        private readonly IList<int> _secondaryIdentifiers;
        private readonly int _id;

        public Record(int id, IList<int> secondaryIdentifiers)
        {
            _id = id;
            _secondaryIdentifiers = secondaryIdentifiers;
        }

        public IList<int> SecondaryIdentifiers
        {
            get { return _secondaryIdentifiers; }
        }

        public int Id
        {
            get { return _id; }
        }
    }

How can I union / interest such that the Union and Intersect operations merge the SecondaryIdentifiers.

        var union = first.Union(second);
        var intersect = first.Intersect(second);

Union will be

            {
                new Record(1, new List<int> { 2, 3 , 4 }),
                new Record(4, new List<int> { 5, 6 })
            };

Intersect will be

            {
                new Record(1, new List<int> { 2, 3 , 4 }),
            };

What I have tried

I tried using a first.Union(second, new EqualityComparer()) where the EqualityComparer extends IEqualityComparer<Record> and merges the two SecondaryIdentifiers if the two items compared are equal, but it seemed a little hacky to me.

Is there a more elegant way of doing this ?

Upvotes: 1

Views: 2160

Answers (2)

Lorentz Vedeler
Lorentz Vedeler

Reputation: 5301

this should work for the union part:

from a in first
join b in second on a.Id equals b.Id into rGroup
let ids = a.SecondaryIdentifiers.Union(rGroup.SelectMany(r => r.SecondaryIdentifiers))
select new Record(a.Id, ids.ToList())

and the intersect:

from a in first
join b in second on a.Id equals b.Id
select new Record(a.Id, a.SecondaryIdentifiers.Union(b.SecondaryIdentifiers).ToList())

Upvotes: 0

L.B
L.B

Reputation: 116108

Is there a more elegant way of doing this

It is opinion based but I would do it as:

var union = first.Concat(second)
            .GroupBy(x => x.Id)
            .Select(g => g.SelectMany(y => y.SecondaryIdentifiers).ToList())
            .ToList();


var intersect = first.Concat(second)
                .GroupBy(x => x.Id)
                .Where(x => x.Count() > 1)
                .Select(g => g.SelectMany(y => y.SecondaryIdentifiers).ToList())
                .ToList();

PS: Feel free to remove .ToList()s for lazy evaluation.

Upvotes: 2

Related Questions