Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to pass multiple objects into a IEnumerable List?

Tags:

c#

.net

list

vb.net

I have this piece of code, which seems to support passing into it many list arguments and it would compare each one against each other one to find a common list among all of the other lists simultaneously.

I cannot figure out how to pass multiple Lists into a single argument thats a IEnmerable.

Say my test code looks like this

List<uint> List1 = new List<uint>();
List<uint> List2 = new List<uint>();
List<uint> List3 = new List<uint>();

List<uint> Commons = FindCommon(List1, List2, List3); //no compile
List<uint> Commons = FindCommon<List<uint>>(List1, List2, List3); //no compile?? why

How do I call this properly?? must I merge them somehow into a IEnumerable?? or must I somehow combine them all into 1 list yet keeping some kind of invisible divider?

 static List<T> FindCommon<T>(IEnumerable<List<T>> lists)
    {
        Dictionary<T, int> map = new Dictionary<T, int>();
        int listCount = 0; // number of lists

        foreach (IEnumerable<T> list in lists)
        {
            listCount++;
            foreach (T item in list)
            {
                // Item encountered, increment count
                int currCount;
                if (!map.TryGetValue(item, out currCount))
                    currCount = 0;

                currCount++;
                map[item] = currCount;
            }
        }

        List<T> result= new List<T>();
        foreach (KeyValuePair<T,int> kvp in map)
        {
            // Items whose occurrence count is equal to the number of lists are common to all the lists
            if (kvp.Value == listCount)
                result.Add(kvp.Key);
        }

        return result;
    }

P.S.> FindCommon is broken somehow it doesn't work properly, probably isn't intended what I thought it should do.. it doesn't check all lists simultaneously together only linear one list at a time with another list which breaks it's purpose, it counts them up.. but it doesn't keep track from which list they came from.

Fixed it like so, this method worked as intended.

public static List<T> FindCommon<T>(params List<T>[] lists)
{
    SortedDictionary<T, bool>
      current_common = new SortedDictionary<T, bool>(),
      common = new SortedDictionary<T, bool>();

    foreach (List<T> list in lists)
    {
        if (current_common.Count == 0)
        {
            foreach (T item in list)
            {
                common[item] = true;
            }
        }
        else
        {
            foreach (T item in list)
            {
                if (current_common.ContainsKey(item))
                {
                    common[item] = true;
                }
            }
        }

        if (common.Count == 0)
        {
            current_common.Clear();
            break;
        }

        SortedDictionary<T, bool>
          swap = current_common;

        current_common = common;
        common = swap;
        common.Clear();
    }

    return new List<T>(current_common.Keys);
}
like image 769
SSpoke Avatar asked Feb 07 '23 23:02

SSpoke


1 Answers

You can accomplish this nicely using the params keyword. In your example:

static List<T> FindCommon<T>(params List<T>[] lists)

That would achieve usage:

List<uint> Commons = FindCommon(List1, List2, List3);
like image 58
Simon Karlsson Avatar answered Feb 11 '23 01:02

Simon Karlsson