2017-02-21 1 views
-1

Sagen, ich habe ein List<Point> { {5,2}, {7,2}, {3,9} }Drehen Liste <T> basierend auf einer Bedingung

Ich mag meine Ausgabe immer mit dem Punkt mit dem kleinsten X-Wert beginnt

So wie etwas:

var output = input.Rotate((x, y) => x.X < y.X)); 
output = `List<Point> { {3,9}, {5,2}, {7,2} }` 

Es ist nicht schwer manuell zu tun:

  1. Finden Sie den Index des Objekts, das die Bedingung erfüllt Ion
  2. eine neue Liste erstellen
  3. alles aus dem Index hinzufügen zu dieser Liste
  4. hinzufügen alles von 0 bis Index-1

ich dort frage mich nur zu beenden, wenn ein LINQ Weg zu tun ist, Dies?

+3

wählen Warum nicht nur 'input.OrderBy (p => pX)'? –

+2

Bitte zeigen Sie Ihren aktuellen Code mit Loops und Ihre Versuche, den LINQ Weg zu tun. Welchen Nutzen hat LINQ für Sie, wonach suchen Sie in potenziellen Antworten? – CodeCaster

+1

OrderBy wird nicht funktionieren. Das OP möchte die Liste so drehen, dass der Punkt mit dem kleinsten X-Wert zuerst angezeigt wird, aber die Reihenfolge der Liste beibehalten wird. – swatsonpicken

Antwort

2

zuerst den minimalen X-Wert finden:

var minX = input.Min(p => p.X); 

nächste das erste Vorkommen erhalten, wobei X das Minimalwert:

var index = input.FindIndex(p => p.X == minX); 

nun eine neue Liste erstellen, indem Sie das Original in zwei Abschnitte aufgeteilt:

var newInput = input.Skip(index).Concat(input.Take(index)); 
+0

Es wäre effizienter, den Index nur in einem Schritt zu erhalten.Sie können zum Beispiel 'Aggregate' verwenden. –

+0

@MattBurland Nicht sicher, es wäre effizienter, aber möglicherweise. 'Aggregate' wäre jedoch viel schwieriger zu lesen. – DavidG

+0

Natürlich wäre es effizienter, zweimal anstelle von dreimal zu schleifen (im schlimmsten Fall - was das Beispiel des OP ist). Für eine kleine Liste mag das nicht wichtig sein, aber es würde sicherlich viel besser skalieren. –

1

Sie es nicht in einem Schritt tun können, werden Sie mindestens zwei Iterationen müssen durch das Array. Aber man könnte diesen (ein bisschen hacky) Ansatz zu tun:

var range = Enumerable.Range(0, list.Count); 
var index = range.Aggregate((p,c) => list[p].X> list[c].X? c : p); 
var rotated = range.Select(i => list[(i + index) % list.Count]).ToList(); 

Hier ist ein example (mit Tuple statt Point, aber es ist das gleiche Prinzip)

Der erste Schritt ist die index des niedrigsten Wertes zu finden in deinem Array. Im zweiten Schritt erstellen sie Ihr neues Array, beginnend mit diesem Index und Schleifen.

Wenn Sie es in einer Verlängerung Methode zum Einkapseln wollten, könnten Sie so etwas tun:

public static IEnumerable<T> Rotate<T>(this List<T> list, Func<T,T, bool> comparer) 
{ 
    var range = Enumerable.Range(0, list.Count); 
    var index = range.Aggregate((p,c) => predicate(list[p],list[c]) ? p : c);  
    return range.Select(i => list[(i + index) % list.Count]); 
} 

Welche du so nennen würde:

var output = input.Rotate((x, y) => x.X < y.X)); 

Sie in eine Funktion übergeben die , wenn es als wahr ausgewertet wird, wird x statt y

Verwandte Themen