nick_green
nick_green

Reputation: 1664

How to map two different lists to one list?

I have two lists of Generic types A and B:

public class A {
    int type;
    string params;
    bool isActive;
}

public class B {
    int type;
}

How could I map them into one list of type A where B.type == A.type (not A.type == B.type!!) using linq?

Instances of class B contain int values that can be deleted or added whereas instances of class A contain values from my db.

So for example:

A[0] = {1, "11", true}, A[1] = {2, "22", true}, A[2] = {3, "33", false}

and

B = {2, 3}

The desired result consists of A[1] and A[2].

Upvotes: 3

Views: 7975

Answers (4)

Marc Gravell
Marc Gravell

Reputation: 1062915

It sounds like what you mean is "filter the items from the first list by checking a property against a second list" - in which case, I would suggest:

  1. build an index from the second list:

    // create an index of the "type"s to look for
    var index = new HashSet<int>(bList.Select(x => x.type));
    
  2. use this to filter the data

    // filter the primary list to values from the index
    var matches = aList.FindAll(x => index.Contains(x.type));
    

This will very efficiently give you a list of just the A data that has corresponding values in the bList.

Here it is runnable:

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    public class A
    {
        public int type;
        public string @params;
        public bool isActive;
    }

    public class B
    {
        public int type;
    }
    static void Main()
    {
        var aList = new List<A>
        {
            new A { type = 1, @params = "11", isActive = true },
            new A { type = 2, @params = "22", isActive = true },
            new A { type = 3, @params = "33", isActive = false },
        };
        var bList = new List<B>
        {
            new B { type = 2 },
            new B { type = 3 },
        };
        // create an index of the "type"s to look for
        var index = new HashSet<int>(bList.Select(x => x.type));

        // filter the primary list to values from the index
        var matches = aList.FindAll(x => index.Contains(x.type));

        foreach (var match in matches)
        {
            Console.WriteLine($"{match.type}, {match.@params}, {match.isActive}");
        }
    }
}

with output:

2, 22, True
3, 33, False

Upvotes: 3

Harald Coppoolse
Harald Coppoolse

Reputation: 30464

If you have two sequences, where both sequence have a value that should match, and you want to take zero or more properties form the first sequence and zero or more properties from the second sequence you use Enumerable.Join.

The syntax seems a bit difficult, but if used more often you get accustomed to it.

Suppose in your example you have a sequence of A objects and a sequence of B objects:

IEnumerable<A> myAobjects = ...
IEnumerable<B> myBobjects = ...

// do the join:
myAObjects.Join(myBobjects,  // join the two sequences
myAobject => myAobject.type, // from the A sequence take property type
myBobject => myBobject.type, // from the B sequence also take property type
(myAobject, myBobject) =>    // whenever the values of these properties equal, take:
 ...);

The dots will be filed with what you want from the combination of a myAobject and a myBobject that have the same value for property type. Your question is simple: whenever a myAobject.type matches a myBobject.type, you want the complete myAObject. In that case the last part of the join is:

(myAobject, myBobject) => myAobject

If you wanted something else returned you would use something like:

(myAobject, myBobject) => new
{
    MyParams = myAobject.Params,
    MyOtherValue = myBObject.type,
}

Upvotes: 0

Robert K
Robert K

Reputation: 106

Is this what you are looking for !?

var result = arrayA.Where(a => arrayB.Select(b => b.type).Contains(a.type)).ToArray();

Upvotes: 1

Tim Schmelter
Tim Schmelter

Reputation: 460158

You want to join both lists, so find all A which are in both lists?

var query = from a in aList
            join b in bList
            on a.type equals b.type
            select a;
List<A> resultList = query.ToList();

Upvotes: 3

Related Questions