C# Permutation of an array of arraylists?

后端 未结 13 819
难免孤独
难免孤独 2020-11-27 18:10

I have an ArrayList[] myList and I am trying to create a list of all the permutations of the values in the arrays.

EXAMPLE: (all values are strings)

         


        
相关标签:
13条回答
  • 2020-11-27 18:35

    I'm surprised nobody posted the LINQ solution.

    from val0 in new []{ "1", "5", "3", "9" }
    from val1 in new []{ "2", "3" }
    from val2 in new []{ "93" }
    select String.Format("val0={0};val1={1};val2={2}", val0, val1, val2)
    
    0 讨论(0)
  • 2020-11-27 18:37

    Recursive solution

        static List<string> foo(int a, List<Array> x)
        {
            List<string> retval= new List<string>();
            if (a == x.Count)
            {
                retval.Add("");
                return retval;
            }
            foreach (Object y in x[a])
            {
                foreach (string x2 in foo(a + 1, x))
                {
                    retval.Add(y.ToString() + " " + x2.ToString());
                }
    
            }
            return retval;
        }
        static void Main(string[] args)
        {
            List<Array> myList = new List<Array>();
            myList.Add(new string[0]);
            myList.Add(new string[0]);
            myList.Add(new string[0]);
            myList[0] = new string[]{ "1", "5", "3", "9" };
            myList[1] = new string[] { "2", "3" };
            myList[2] = new string[] { "93" };
            foreach (string x in foo(0, myList))
            {
                Console.WriteLine(x);
            }
    
            Console.ReadKey();
        }
    

    Note that it would be pretty easy to return a list or array instead of a string by changing the return to be a list of lists of strings and changing the retval.add call to work with a list instead of using concatenation.

    How it works:

    This is a classic recursive algorithm. The base case is foo(myList.Count, myList), which returns a List containing one element, the empty string. The permutation of a list of n string arrays s1, s2, ..., sN is equal to every member of sA1 prefixed to the permutation of n-1 string arrays, s2, ..., sN. The base case is just there to provide something for each element of sN to be concatenated to.

    0 讨论(0)
  • 2020-11-27 18:43

    I recently ran across a similar problem in a project of mine and stumbled on this question. I needed a non-recursive solution that could work with lists of arbitrary objects. Here's what I came up with. Basically I'm forming a list of enumerators for each of the sub-lists and incrementing them iteratively.

    public static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<IEnumerable<T>> lists)
    {
        // Check against an empty list.
        if (!lists.Any())
        {
            yield break;
        }
    
        // Create a list of iterators into each of the sub-lists.
        List<IEnumerator<T>> iterators = new List<IEnumerator<T>>();
        foreach (var list in lists)
        {
            var it = list.GetEnumerator();
            // Ensure empty sub-lists are excluded.
            if (!it.MoveNext())
            {
                continue;
            }
            iterators.Add(it);
        }
    
        bool done = false;
        while (!done)
        {
            // Return the current state of all the iterator, this permutation.
            yield return from it in iterators select it.Current;
    
            // Move to the next permutation.
            bool recurse = false;
            var mainIt = iterators.GetEnumerator();
            mainIt.MoveNext(); // Move to the first, succeeds; the main list is not empty.
            do
            {
                recurse = false;
                var subIt = mainIt.Current;
                if (!subIt.MoveNext())
                {
                    subIt.Reset(); // Note the sub-list must be a reset-able IEnumerable!
                    subIt.MoveNext(); // Move to the first, succeeds; each sub-list is not empty.
    
                    if (!mainIt.MoveNext())
                    {
                        done = true;
                    }
                    else
                    {
                        recurse = true;
                    }
                }
            }
            while (recurse);
        }
    }
    
    0 讨论(0)
  • 2020-11-27 18:45

    One of the problems I encountred when I was doing this for a very large amount of codes was that with the example brian was given I actually run out of memory. To solve this I used following code.

    static void foo(string s, List<Array> x, int a)
        {
            if (a == x.Count)
            {
                // output here
                Console.WriteLine(s);
            }
            else
            {
                foreach (object y in x[a])
                {
                    foo(s + y.ToString(), x, a + 1);
                }
            }
        }
    
    static void Main(string[] args)
        {
            List<Array> a = new List<Array>();
            a.Add(new string[0]);
            a.Add(new string[0]);
            a.Add(new string[0]);
            a[0] = new string[] { "T", "Z" };
            a[1] = new string[] { "N", "Z" };
            a[2] = new string[] { "3", "2", "Z" };
    
            foo("", a, 0);
            Console.Read();
        }
    
    0 讨论(0)
  • 2020-11-27 18:45
    private static void GetP(List<List<string>> conditions, List<List<string>> combinations, List<string> conditionCombo, List<string> previousT, int selectCnt)
    {
        for (int i = 0; i < conditions.Count(); i++)
        {
            List<string> oneField = conditions[i];
            for (int k = 0; k < oneField.Count(); k++)
            {
                List<string> t = new List<string>(conditionCombo);
                t.AddRange(previousT);
                t.Add(oneField[k]);
    
                if (selectCnt == t.Count )
                {
                    combinations.Add(t);
                    continue;
                }
                GetP(conditions.GetRange(i + 1, conditions.Count - 1 - i), combinations, conditionCombo, t, selectCnt);
            }
    
        }
    }
    
    List<List<string>> a = new List<List<string>>();
    a.Add(new List<string> { "1", "5", "3", "9" });
    a.Add(new List<string> { "2", "3" });
    a.Add(new List<string> { "93" });
    List<List<string>> result = new List<List<string>>();
    GetP(a, result, new List<string>(), new List<string>(), a.Count);
    

    Another recursive function.

    0 讨论(0)
  • 2020-11-27 18:46

    This will work no matter how many arrays you add to your myList:

            static void Main(string[] args)
            {
                string[][] myList = new string[3][];
                myList[0] = new string[] { "1", "5", "3", "9" };
                myList[1] = new string[] { "2", "3" };
                myList[2] = new string[] { "93" };
    
                List<string> permutations = new List<string>(myList[0]);
    
                for (int i = 1; i < myList.Length; ++i)
                {
                    permutations = RecursiveAppend(permutations, myList[i]);
                }
    
                //at this point the permutations variable contains all permutations
    
            }
    
            static List<string> RecursiveAppend(List<string> priorPermutations, string[] additions)
            {
                List<string> newPermutationsResult = new List<string>();
                foreach (string priorPermutation in priorPermutations)
                {
                    foreach (string addition in additions)
                    {
                        newPermutationsResult.Add(priorPermutation + ":" + addition);
                    }
                }
                return newPermutationsResult;
            }
    

    Note that it's not really recursive. Probably a misleading function name.

    Here is a version that adheres to your new requirements. Note the section where I output to console, this is where you can do your own formatting:

    static void Main(string[] args)
            {
                string[][] myList = new string[3][];
                myList[0] = new string[] { "1", "5", "3", "9" };
                myList[1] = new string[] { "2", "3" };
                myList[2] = new string[] { "93" };
    
                List<List<string>> permutations = new List<List<string>>();
    
                foreach (string init in myList[0])
                {
                    List<string> temp = new List<string>();
                    temp.Add(init);
                    permutations.Add(temp);
                }
    
                for (int i = 1; i < myList.Length; ++i)
                {
                    permutations = RecursiveAppend(permutations, myList[i]);
                }
    
                //at this point the permutations variable contains all permutations
    
                foreach (List<string> list in permutations)
                {
                    foreach (string item in list)
                    {
                        Console.Write(item + ":");
                    }
                    Console.WriteLine();
                }
    
            }
    
            static List<List<string>> RecursiveAppend(List<List<string>> priorPermutations, string[] additions)
            {
                List<List<string>> newPermutationsResult = new List<List<string>>();
                foreach (List<string> priorPermutation in priorPermutations)
                {
                    foreach (string addition in additions)
                    {
                        List<string> priorWithAddition = new List<string>(priorPermutation);
                        priorWithAddition.Add(addition);
                        newPermutationsResult.Add(priorWithAddition);
                    }
                }
                return newPermutationsResult;
            }
    
    0 讨论(0)
提交回复
热议问题