2012-04-10 3 views
0

Liste:Neuordnungs Liste beginnend bei bestimmten Position

List<int> list1 = new List<int>(){ 0, 1, 2, 3, 4, 5, 6 }; 

wir sagen, dass wir es neu anordnen möchten. Der Anfang sollte Nummer "2"

// 2,3,4,5,6,0,1 

oder an der Hausnummer 5

// 5,6,0,1,2,3,4 

sein, wie Sie es mit C# tun?

Der Grund: Stellen Sie sich vor, Sie haben einen Index einer bestimmten Nummer in der Liste (Nummer 3, Index 3). Sie wollen die zweite Nummer von rechts bekommen - es wird 5.

Leider, wenn die Startnummer ist am Ende der Liste (Nummern 5 und 6) - Out-of-Range-Ausnahme wird geworfen , weil es keine 7 und 8 gibt!

Die Idee ist, die Liste neu zu ordnen!

  • Wir geben Nr. Ein. 5 - wir bekommen 0 (5,6,0).
  • Wir geben Nr. 6 - wir bekommen 1 (6,0,1), usw.

oder gibt es noch eine andere (besser lesbare) Möglichkeit, dieses Problem zu lösen?

Antwort

2

Sie müssen die Liste nicht neu anordnen. Sie können die Nummer mit der folgenden Funktion erhalten:

int GetNumber(List<int> list, int fromValue, int index) 
{ 
    return list[(list.IndexOf(fromValue) + index) % list.Count()]; 
} 

Sie könnten die Funktion wie folgt aufrufen:

List<int> list1 = new List<int>(new[] { 0, 1, 2, 3, 4, 5, 6 }); 
int number = GetNumber(list1, 5, 2); // number = 0 
+0

großartige Ergänzung zu Matts Antwort! Vielen Dank! – Alex

+0

Sind Sie sicher, dass die '- 1' notwendig ist? –

+0

@ OlivierJacot-Descombes: Ich habe die "-1" hinzugefügt, um das erwartete Verhalten des OP zu erreichen (Index von 3 = zwei auf der rechten Seite). –

4

Der bessere Weg ist, den Mod-Operator% zu verwenden. Dies gibt Ihnen den Rest, wenn Sie ein int durch ein anderes int teilen. Die Art und Weise dies funktioniert, ist so etwas wie diese:

int nextIndex = (currentIndex + offset) % length; 

Also, wenn Ihr aktueller Index 5 ist, Ihre Offset 2 und Ihre Länge beträgt 6 dann:

5 + 2 = 7 
7/6 = 1 remainder 1 (or 7 mod 6 = 1) 
therefore nextIndex = 1 
+0

danke für die Erklärung! – Alex

3

Ein wenig Linq dies tun kann ziemlich einfach:

List<int> list1 = new List<int>(new[] { 0, 1, 2, 3, 4, 5, 6 }); 

var numToStart = 4; 

//reorderedList will be {4,5,6,0,1,2,3} 
var reorderedList = list1.Skip(numToStart).Concat(list1.Take(numToStart)); 
+0

Dies sollte funktionieren, aber es wird die gesamte Liste neu erstellt, anstatt nur die Elemente zu verschieben, oder die von den anderen bereitgestellten Lösungen, die keine Listenmutation enthalten. – Servy

+0

Nein ist es nicht; Es durchläuft die Liste in einer bestimmten Weise, die von den Methoden definiert wird. Skip() und Take() müssen intern nicht neu angelegt werden, wie OrderBy() und GroupBy() tun; Sie listen einfach ihre Quellensammlung mit der durch den Namen implizierten Wendung auf (so als würden sie die ersten X-Gegenstände nicht ergeben oder NUR die ersten X-Gegenstände ergeben). Nun, wenn Sie die neu geordneten Elemente tatsächlich beibehalten müssten, dann wäre das nicht in-Place, aber das scheint keine Anforderung zu sein, und eine In-Place-Lösung wäre komplexer. – KeithS

+0

Die Anforderungen des OP würden beinhalten, die Ergebnisse der Abfrage als Liste zu speichern.Wenn Sie dies nicht tun und diese Abfrage jedes Mal ausführen, dann drehen Sie eine O (1) -Listensuche in eine O (n) -Lookup, so dass es immer noch eine wesentlich schlechtere Lösung ist. – Servy