Naty Bizz
Naty Bizz

Reputation: 2342

Add values from a list of objects to another list of different objects

I have this scenario

class A
{
    public string id { get; set; }
    public string val1 { get; set; }
    public string val2 { get; set; }
    public string val3 { get; set; }
    public string val4 { get; set; }
    public string val5 { get; set; }
}

class B
{
    public string id { get; set; }
    public string val2 { get; set; }
    public string val3 { get; set; }
}

List<A> lista = new List<A>(); //10 items

List<B> listb = new List<B>(); //400 items

I want to store in A, the values of B that match the id field (val2 and val3 of B into val2 and val3 of A, by id) , how can I do this?

Upvotes: 0

Views: 695

Answers (3)

John Wu
John Wu

Reputation: 52250

Creating new objects

You can use LINQ/Select to convert the B's into A's and add them with AddRange.

lista.AddRange
(
    listb.Select
    (
        b => new A 
        { 
            id   = b.id, 
            val2 = b.val2, 
            val3 = b.val3 
        } 
    )
);

Putting both types of objects in the same list

Or, if you literally want to store both A's and B's in the same list, you can set up an inheritance relationship:

class B
{
    public string id { get; set; }
    public string val2 { get; set; }
    public string val3 { get; set; }
}

class A : B
{
    public string val1 { get; set; }
    public string val4 { get; set; }
    public string val5 { get; set; }
}

var listb = new List<B>();

Now your list can store both A and B, because A is a specialization of B. So you can do this:

listb.AddRange(lista);

Updating in place

If you want to keep the original objects in lista and just want to update the matching properties, you should probably use a loop. It's possible to do it with LINQ if you really want, but it's really not "meant" for updating things in place.

It does make things a little easier to store your As in a dictionary, since you get the lookup ability. A dictionary uses a hash table internally so you will also get better performance than a scan. Because the dictionary only contains references, the objects in the original list will get updated too.

var dictionarya = lista.ToDictionary
(
    item => item.id,
    item => item
);
foreach (var b in listb)
{
    A a;
    if (dictionarya.TryGetValue(b.id, out a))
    {
        a.val2 = b.val2;
        a.val3 = b.val3;
    }
}

Upvotes: 1

Ousmane D.
Ousmane D.

Reputation: 56433

Seems like a good job for the Join clause:

var result = lista.Join(listb,
                       a => a.id,
                       b => b.id,
                       (a, b) => 
                       new A { id = a.id, val2 = b.val2, val3 = b.val3 });

This will accomplish your description of "I want to store in A, the values of B that match the id field".

if instead, you want to accumulate the result from the Join clause to lista, then you can utilise the AddRange method:

lista.AddRange(result);

Upvotes: 0

Jonathon Chase
Jonathon Chase

Reputation: 9704

The following LINQ query should get you there:

lista.AddRange(from b in listb
               let a = new A { id = b.id, val2 = b.val2, val3 = b.val3}
               where lista.Any(x => x.id == a.id)
               select a);

This will select a list of all B that share an ID with a value in lista, then add the result to lista.

Upvotes: 1

Related Questions