简体   繁体   中英

How to add List<T> items dynamically to IEnumerable<T>

Code

public static void Main()
{
    List<int> list1 = new List<int> {1, 2, 3, 4, 5, 6 };
    List<int> list2 = new List<int> {1, 2, 3 };
    List<int> list3 = new List<int> {1, 2 };
    var lists = new IEnumerable<int>[] { list1, list2, list3 };
    var commons = GetCommonItems(lists);
    Console.WriteLine("Common integers:");
    foreach (var c in commons)
        Console.WriteLine(c);
}

static IEnumerable<T> GetCommonItems<T>(IEnumerable<T>[] lists)
{
    HashSet<T> hs = new HashSet<T>(lists.First());
    for (int i = 1; i < lists.Length; i++)
        hs.IntersectWith(lists[i]);
    return hs;
}

As for the sample, I showed "list1" "list2" "list3", but I may have more than 50 lists that are generating each list using for each loop. How can I add programmatically each "list" to IEnumerable lists for comparing data of each list?

I tried many ways like conversion to list, Add, Append, Concat but nothing worked.

Is there any other best way to compare the N number of lists?

The output of Code: 1 2

You can create a list of lists and add lists to that list dynamically. Something like this:

var lists = new List<List<int>>();
lists.Add(new List<int> {1, 2, 3, 4, 5, 6 });
lists.Add(new List<int> {1, 2, 3 });
lists.Add(new List<int> {1, 2 });

foreach (var list in listSources)
    lists.Add(list);

var commons = GetCommonItems(lists);

To find intersections you can use this solution for example: Intersection of multiple lists with IEnumerable.Intersect() (actually looks like that's what you are using already).

Also make sure to change the signature of the GetCommonItems method:

static IEnumerable<T> GetCommonItems<T>(List<List<T>> lists)

What you could do is allow the GetCommonItems method to accept a variable amount of parameters using the params keyword. This way, you avoid needing to create a new collection of lists.

It goes without saying, however, that if the amount of lists in your source is variable as well, this could be trickier to use.

I've also amended the GetCommonItems method to work like the code from https://stackoverflow.com/a/1676684/9945524

public static void Main()
{
    List<int> list1 = new List<int> { 1, 2, 3, 4, 5, 6 };
    List<int> list2 = new List<int> { 1, 2, 3 };
    List<int> list3 = new List<int> { 1, 2 };

    var commons = GetCommonItems(list1, list2, list3); // pass the lists here

    Console.WriteLine("Common integers:");
    foreach (var c in commons)
        Console.WriteLine(c);
}

static IEnumerable<T> GetCommonItems<T>(params List<T>[] lists)
{
    return lists.Skip(1).Aggregate(
        new HashSet<T>(lists.First()),
        (hs, lst) =>
        {
            hs.IntersectWith(lst);
            return hs;
        }
    );
}

Alternate solution using your existing Main method.

EDIT: changed the type of lists to List<List<int>> as per comment in this answer.

public static void Main()
{
    List<int> list1 = new List<int> { 1, 2, 3, 4, 5, 6 };
    List<int> list2 = new List<int> { 1, 2, 3 };
    List<int> list3 = new List<int> { 1, 2 };
    var lists = new List<List<int>> { list1, list2, list3 };
    var commons = GetCommonItems(lists);
    Console.WriteLine("Common integers:");
    foreach (var c in commons)
        Console.WriteLine(c);
}

static IEnumerable<T> GetCommonItems<T>(List<List<T>> lists)
{
    return lists.Skip(1).Aggregate(
        new HashSet<T>(lists.First()),
        (hs, lst) =>
        {
            hs.IntersectWith(lst);
            return hs;
        }
    );
}
  1. IEnumerable is immutable so you always should return an implementation of IEnumerable depending on your needs.
  2. If I understand correctly you want to get common items of N lists. I would use LINQ for this.

My proposition: 1. make one list that contains all of the items. =>

var allElements = new List<int>();
  var lists = new List<List<int>>();
foreach (list in lists)
    allElements.AddRange(list);
  1. Take items that are repetitive

allElements.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x).ToList();

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