2016-04-22 5 views
1

Ich weiß, der übliche Ansatz für "variable Anzahl von for Schleifen" soll eine rekursive Methode verwenden. Aber ich frage mich, ob ich das ohne Rekursion lösen könnte und stattdessen mit Stack, da Sie Rekursion mit der Verwendung eines Stapels umgehen können.Variable Anzahl von for-Schleifen ohne Rekursion aber mit Stack?

Mein Beispiel:
Ich habe eine variable Anzahl von Sammlungen und ich brauche jedes Element jeder Kollektion mit jedem anderen Punkt der anderen Sammlungen zu kombinieren.

// example for collections A, B and C: 
A (4 items) + B (8 items) + C (10 items) 
4 * 8 * 10 = 320 combinations 

Ich muss alle diese 320 Kombinationen durchlaufen. Zur Kompilierzeit weiß ich nicht, ob B oder C oder D existieren. Wie würde eine Lösung ohne rekursive Methode, aber mit der Verwendung einer Instanz von Stack aussehen?

Edit:
Ich erkennen Stapel nicht notwendig ist, hier überhaupt, während Sie die Rekursion mit einem einfachen int-Array und ein paar While-Schleifen zu vermeiden. Danke für Hilfe und Info.

+2

Nun, technisch gesehen, wird unter Verwendung von Rekursion das im Programm Funktionsaufruf-Stack: p – Nyerguds

+2

Meine Frage wäre: Da eine rekursive Methode die offensichtliche logische Wahl für ein solches Problem ist, warum möchten Sie die Lösung unnötig kompliziert machen? Es ist wie die Frage "Wie kann ich 5.5 und 4.6 nur mit Ints hinzufügen?" – phil13131

+0

@ phil13131 Ihr Beispiel ist unmöglich. Sagst du, meine Frage fragt nach dem Unmöglichen? Ich denke nicht. – Bitterblue

Antwort

0

Hier ist ein Beispiel dafür, wie dies zu tun. Der Algorithmus wird aus dieser Frage - https://stackoverflow.com/a/2419399/5311735 - entnommen und in C# umgewandelt. Beachten Sie, dass es effizienter gemacht werden kann, aber ich umgewandelt ineffizient Version C#, weil es besser ist das Konzept zeigt (Sie effizientere Version in der verknüpften Frage sehen):

static IEnumerable<T[]> CartesianProduct<T>(IList<IList<T>> collections) { 
     // this contains the indexes of elements from each collection to combine next 
     var indexes = new int[collections.Count]; 
     bool done = false; 
     while (!done) { 
      // initialize array for next combination 
      var nextProduct = new T[collections.Count]; 
      // fill it 
      for (int i = 0; i < collections.Count; i++) { 
       var collection = collections[i]; 
       nextProduct[i] = collection[indexes[i]]; 
      } 
      yield return nextProduct; 
      // now we need to calculate indexes for the next combination 
      // for that, increase last index by one, until it becomes equal to the length of last collection 
      // then increase second last index by one until it becomes equal to the length of second last collection 
      // and so on - basically the same how you would do with regular numbers - 09 + 1 = 10, 099 + 1 = 100 and so on. 

      var j = collections.Count - 1; 
      while (true) { 
       indexes[j]++; 
       if (indexes[j] < collections[j].Count) { 
        break; 
       } 
       indexes[j] = 0; 
       j--; 
       if (j < 0) { 
        done = true; 
        break; 
       } 
      } 
     } 
    } 
+0

Ich baue gerade eine Funktion selbst, die ziemlich das selbe tut. – Bitterblue

2

Nicht mit einem Stapel, aber ohne Rekursion.

void Main() 
{ 
    var l = new List<List<int>>() 
    { 
     new List<int>(){ 1,2,3 }, 
     new List<int>(){ 4,5,6 }, 
     new List<int>(){ 7,8,9 } 
    }; 

    var result = CartesianProduct(l); 
} 

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences) 
{ 
    IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>()}; 
    return sequences.Aggregate(
     emptyProduct, 
     (accumulator, sequence) => 
      from accseq in accumulator 
      from item in sequence 
      select accseq.Concat(new[] {item})      
     ); 
} 

Funktion genommen Form Computing a Cartesian Product with LINQ

+0

[Hier ist der Quellartikel (von Eric Lippert) für den Code oben] (https://blogs.msdn.microsoft.com/ericlippert/2010/06/28/computing-a-cartesian-product-with-linq/) Und [hier ist die ursprüngliche SO-Antwort, woher dieser Code stammt] (http://stackoverflow.com/a/3098381/106159) –

+0

Versteh ich das richtig oder haben Sie gerade die Rekursivität in Standard-Bibliotheken versteckt (; – phil13131

+0

@ phil13131 Es gibt keine Rekursion in den linq Funktionen, die hier benutzt werden. – Magnus