2017-02-04 3 views
2

Stellen Sie sich vor, ich wollte von A nach Z iterieren. Wir würden entweder Foreach oder For loop verwenden. Nachdem ich Z erreicht habe, möchte ich dann von AA nach ZZ iterieren, also beginnt es bei AA und geht dann zu AB, AC ... AZ, BA, BC..BZ..ZA, ZB, ZZ. An diesem Punkt würden wir zu drei chars, dann 4 usw. bis zu einem undefinierten Punkt gehen.C# wiederhole ein kontinuierlich wachsendes multidimensionales Array

Weil wir uns verschachtelte for Schleifen keine definierte Länge für das Array haben nicht verwenden können ... so

Frage: Wie dies geschehen kann?

Hinweis hat kein Code angegeben, weil wir alle wissen, wie foreach Schleifen ein Array und Nest zu foreach über.

Antwort

1

Der Weg ist einfach rekursive Vorgehensweise. C# ist eine gute Idee, eine Sprache mit dem Einsatz von Generatoren zu präsentieren:

private static IEnumerable<string> EnumerateLetters(int length) { 
    for (int i = 1; i <= length; i++) { 
     foreach (var letters in EnumerateLettersExact(i)) {     
      yield return letters; 
     } 
    } 
} 

private static IEnumerable<string> EnumerateLettersExact(int length) { 
    if (length == 0) { 
     yield return ""; 
    } 
    else { 
     for (char c = 'A'; c <= 'Z'; ++c) { 
      foreach (var letters in EnumerateLettersExact(length - 1)) { 
       yield return c + letters; 
      } 
     }  
    } 
} 

private static void Main(string[] args) { 
    foreach (var letters in EnumerateLetters(2)) { 
     Console.Write($"{letters} "); 
    } 
} 

EnumerateLetters sukzessive Buchstabenfolgen erzeugt. Der Parameter legt fest, bis zu welcher Länge Sie Sequenzen anfordern möchten.

EnumerateLettersExact kümmert sich um die rekursive Generierung von Sequenzen. Es kann entweder leer sein oder eine Verkettung eines Buchstabens mit allen Sequenzen kürzerer Länge.

0

Sie haben ein Array von A bis Z [A, ..., Z]. Sie gehen dann mehrere für Schleifen

zum Beispiel machen:

PSEUDOCODE 
foreach(in array){ 
    first = declare first variable (array) 
    foreach(in array{ 
      second =declare 2nd variable (array) 
      return first + second 
    } 
} 
+0

Leider bedeutet das, ich muss wissen, wie viele verschachtelte For-Schleifen ich benötigen würde. Es könnte 100 Schleifen sein, was viel zu viel ist, um wirklich zu nisten. –

+0

@Dave Gorden Kennen Sie die Anzahl der Loops, die Sie möchten, bevor es beginnt? –

+0

Nein, die Anzahl der Iterationen ist unbekannt. –

1

Sie so etwas tun könnte, es gibt mir von Ihrem Muster (sorry unending Ausgang, nicht Ihr Muster exakt, aber Sie verstehen, wie es zu tun)

public static IEnumerable<string> Produce() 
{ 
    string seed = "A"; 
    int i = 0; 
    while (true) 
    { 
     yield return String.Join("", Enumerable.Repeat(seed, i));     
     if (seed == "Z") 
     { 
      seed = "A"; 
      i++; 
     } 
     else 
     { 
      seed = ((char)(seed[0]+1)).ToString(); 
     } 
    } 
} 

Und als:

foreach (var s in Produce()) 
{ 
    //Do something 
} 

EDIT I-Ausgang mit dieser Methode gewünscht haben:

public static IEnumerable<string> Produce() 
{ 
    int i = 1; 
    while (true) 
    { 
     foreach(var c in produceAmount(i)) 
     { 
      yield return c; 
     } 
     i++; 
    } 
} 

private static IEnumerable<string> produceAmount(int i) 
{ 
    var firstRow = Enumerable.Range('A', 'Z' - 'A'+1).Select(x => ((char)x).ToString()); 
    if (i >= 1) 
    { 
     var second = produceAmount(i - 1); 
     foreach (var c in firstRow) 
     { 
      foreach (var s in second) 
      { 
       yield return c + s; 
      } 
     } 
    } 
    else 
    { 
     yield return ""; 
    } 
} 
+0

Ihr erstes geht AA, BB, CC, DD (nach vielen Leerzeichen - Sie müssen ich bei 1 beginnen) und Ihre Sekunde geht richtiger AA, AB ... AZ aber dann geht BZ, CZ, DZ ... – Chris

1

Hier einige Code, der das tun, was Sie wollen. Vollständige Erklärung folgt aber in Zusammenfassung nimmt es sich die Tatsache zunutze, dass, sobald Sie alle Buchstaben einer bestimmten Länge getan haben Sie durch diese gesamte Sequenz A folgte sie dann wieder durch die gesamte Sequenz erneut gefolgt B usw.

private IEnumerable<string> EnumerateLetters() 
{ 
    int count = 1; 
    while (true) 
    { 
     foreach(var letters in EnumerateLetters(count)) 
     { 
      yield return letters; 
     } 
     count++; 
    } 
} 

private IEnumerable<string> EnumerateLetters(int count) 
{ 
    if (count==0) 
    { 
     yield return String.Empty; 
    } 
    else 
    { 
     char letter = 'A'; 
     while(letter<='Z') 
     { 
      foreach(var letters in EnumerateLetters(count-1)) 
      { 
       yield return letter+letters; 
      } 
      letter++; 
     } 
    } 
} 

Es gibt zwei Methoden. Der erste ist der, den Sie anrufen und wird eine unendliche Folge von Buchstaben erzeugen. Die zweite macht die Rekursionsmagie.

Die erste ist ziemlich einfach. es zählt, wie viele Buchstaben wir haben, ruft die zweite Methode mit dieser Zählung auf und zählt sie dann auf, indem er sie zurückgibt. Sobald es alles für eine Größe getan hat, erhöht es die Anzahl und Schleifen.

Die zweite Methode ist die, die die Magie macht. Es zählt die Anzahl der Buchstaben in der generierten Zeichenfolge. Wenn der Zählerstand null ist, wird eine leere Zeichenfolge zurückgegeben, und es wird abgebrochen.

Wenn die Anzahl mehr als eins ist, wird es durch die Buchstaben A bis Z durchlaufen und für jeden Buchstaben wird die Sequenz angehängt, die um eins kürzer ist als an die A. Dann für die B und so weiter.

Dies wird dann unbegrenzt weitergehen.

Die Sequenz wird unbegrenzt weitergezählt. Da die Rekursion verwendet wird, wäre es theoretisch möglich, den Stapelüberlauf zu starten, wenn die Buchstabenfolge zu lang wird, aber auf einer Rekursionsebene pro Buchstabe in der Zeichenfolge müssen Sie sehr lange Strings aufstellen, bevor Sie sich darum kümmern müssen (und ich vermute, wenn du so weit in eine Schleife gegangen bist, dass du zuerst andere Probleme hast).Der andere wichtige Punkt (wenn Sie sich dessen nicht bewusst sind) ist, dass yield return eine verzögerte Ausführung verwendet, so dass jedes neue Element in der Sequenz wie benötigt generiert wird, sodass es nur so viele Elemente generiert, wie Sie verlangen. Wenn Sie fünf Mal iterieren, wird nur A-E generiert und Sie haben keine Zeit damit verschwendet, darüber nachzudenken, was als nächstes kommt.

1

Noch ein weiterer Generator (Hinzufügen 1 auf eine Zahl mit radix == 26: A für 1 für 0, B steht, ... Z für 25):

// please, notice, that Generator() can potentially spawn ifinitely many items 
private static IEnumerable<String> Generator() { 
    char[] data = new char[] { 'A' }; // number to start with - "A" 

    while (true) { 
    yield return new string(data); 

    // trying to add one 
    for (int i = data.Length - 1; i >= 0; --i) 
     if (data[i] == 'Z') 
     data[i] = 'A'; 
     else { 
     data[i] = (char) (data[i] + 1); 

     break; 
     } 

    // have we exhausted N-length numbers? 
    if (data.All(item => item == 'A')) 
     data = Enumerable 
     .Repeat('A', data.Length + 1) // ... continue with N + 1-length numbers 
     .ToArray(); 
    } 
} 

-Test

// take first 1000 items: 
    foreach (var item in Generator().Take(1000)) 
    Console.WriteLine(item); 

Ergebnis

A 
    B 
    C 
    .. 
    X 
    Y 
    Z 
    AA 
    AB 
    .. 
    AZ 
    BA 
    BB 
    BC 
    .. 
    ZY 
    ZZ 
    AAA 
    AAB 
    AAC 
    .. 
    ALK 
    ALL 
0

Versuchen Sie Folgendes. Dies ist eine Methode, um die entsprechende Zeichenfolge für eine bestimmte Zahl zu generieren. Sie können eine for-Schleife für beliebig viele Iterationen schreiben.

string SingleEntry(int number) 
{ 
    char[] array = " ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToArray(); 
    Stack<string> entry = new Stack<string>(); 
    List<string> list = new List<string>(); 
    int bas = 26; 

    int remainder = number, index = 0; 
    do 
    { 
     if ((remainder % bas) == 0) 
     { 
      index = bas; 
      remainder--; 
     } 
     else 
      index = remainder % bas; 

     entry.Push(array[index].ToString()); 
     remainder = remainder/bas; 
    } 
    while (remainder != 0); 

    string s = ""; 
    while (entry.Count > 0) 
    { 
     s += entry.Pop(); 
    } 
    return s; 
}