简体   繁体   中英

Given two lists of different objects, how to combine values from each into a new list based on a common Id, efficiently?

What I am trying to do is combine two lists of different types into a new type, on the Id property of each. Both lists have different properties that I need in the new list.

This snippet is working already, but I am not happy with the performance. Assuming both lists are the same length, and in whatever order they need to be, is it possible to do this more efficiently?

class A
{
    public int Id { get; set; }
    public string stuffA { get; set; }
    //other properties that we aren't using
}
class B
{
    public int Id { get; set; }
    public string stuffB { get; set; }
    //other properties we aren't using
}
class C
{
    public int Id { get; set; }
    public string stuffA { get; set; }
    public string stuffB { get; set; }
}
public List<C> getList(List<A> listA, List<B> listB)
{
    var listC = new List<C>();
    
    foreach(var a in listA)
    {
        var b = listB.Where(x => x.Id == a.Id);
        listC.Add(new C{ Id = a.Id, stuffA = a.stuffA, stuffB = b.stuffB});
    }
    return listC;
}

I've looked into the Enumerable.Zip method, which pairs up two lists in the order provided, but I can't seem to use that with objects. The only examples I can make work are with primitive types.

I've seen this question: How merge two lists of different objects? but this doesn't create a new type, only an anonymous type containing the old lists (I believe).

Any ideas?

Your looking for a simple Linq join , the order of items doesn't matter. For example:

public List<C> getList(List<A> listA, List<B> listB)
{
    var listC = from a in listA
                join b in listB on a.Id equals b.Id
                select new C 
                {
                    Id = a.Id,
                    stuffA = a.stuffA,
                    stuffB = b.stuffB
                };

    return listC.ToList();
}

If you can ensure that both lists are in the same order with the same number of elements, you can loop through the lists and join based on index. This eliminates any searches required:

public List<C> getList(List<A> listA, List<B> listB)
{
    var listC = new List<C>();

    for(var i = 0; i < listA.Count; i++)
    {
        listC.Add(new C 
        {
            Id = listA[i].Id,
            stuffA = listA[i].stuffA,
            stuffB = listB[i].stuffB
        };
    }

    return listC;
}

This sounds a bit like a homework question but anyway... the trivial solution has a complexity of O(n^2). if efficiency is your goal, you need to use a structure that allows for fast searching like a hashtable, then your solution will be O(n). so add the elements of the first array to a hash table, then loop thru the second array and compose the result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM