2016-08-08 9 views
1

Ich habe eine Liste von Punkten, die eine Ebene bilden. Ich möchte Kanten zwischen aufeinanderfolgenden Punkten erstellen und sie zu einer anderen Liste hinzufügen. HierWie durchläuft man eine Liste, so dass der letzte Iterationsschritt zum ersten Objekt zurückkehrt?

ist der Code, den ich derzeit haben:

// Get points forming the plate 
ArrayList points = part.points; 

// Number of points forming the plate 
int pointCount = points.Count; 

// Create edges 
List<LineSegment> edges = new List<LineSegment>(); 
for (int i = 0; i < pointCount - 1; i++) 
{ 
    // Get start and end points 
    Point start = points[i]; 
    Point end = points[i+1]; 

    // Create edge 
    LineSegment edge = new LineSegment(start, end); 

    // Add edge to the list 
    edges.Add(edge); 
} 

Es ist nicht ganz funktioniert, weil es nicht schaffen die letzte Kante zwischen dem letzten und die ersten Punkte auf der Liste. Wie könnte man das korrigieren?

for (int i = 0; i < pointCount; i++) 
{ 
    // Get start and end points 
    Point start = points[i] as Point; 
    Point end; 
    if (i == pointCount-1) end = points[0] as Point; 
    else end = points[i+1] as Point; 

    // Rest of the code here 
} 

Aber ich bin sicher, es ist ein eleganter Weg, es zu tun: Ich konnte es mit einer if-Anweisung wie dies funktioniert. In Python würde ich die Schleife von -1 starten, so dass die erste Kante tatsächlich den letzten Punkt mit dem ersten verbinden würde, aber das ist in C# nicht möglich.

EDIT: Die Liste der Punkte wird von der API als ArrayList angegeben.

+2

Abgesehen von Frage, verwenden Sie 'List ' anstelle von 'ArrayList'. Dadurch erhalten Sie eine typisierte Sammlung. – Habib

+0

Warum nicht die Schleife so wie sie ist und den letzten Schritt außerhalb der Schleife machen? Sollte immer der gleiche Befehl sein, Verknüpfung zwischen Punkten [0] und Punkten [Punkte.Länge-1]. –

+0

Nicht wirklich sicher über den Downvote, das sieht wie eine gute Frage aus – Habib

Antwort

7

Ein 'elegant' Lösung wird unter Verwendung einer modulo:

for (int i = 0; i < pointCount; i++) 
{ 
    … 
    // for i+1 == pointCount this will yield points[0] 
    Point end = points[(i+1) % pointCount] as Point; 
    … 
} 

Aber ich glaube, die if Anweisung Sie ist besser lesbar verwendet.

Hinweis: Verwenden Sie auch einen List<T> anstelle von ArrayList.

0

Verwenden Sie den Modulo-Operator (der in C# "%" ist).

0

Ich würde alle aus allen Indizes und expliziten Schleifen töten und das Problem selbst beschreiben, anstatt zu lösen.

var offsetPoints = points.Skip(1).Concat(new[]{points.First()}); 

List<LineSegment> edges = 
    points.Zip(offsetPoints, (p1, p2) => new LineSegment(p1, p2)).ToList(); 

ich eine Offset-Liste nur erstellen, die das erste Element beim Start überspringt und am Ende fügt ihn so die Offset-Liste und die ursprüngliche Liste die gleiche Länge hat.

Zur Illustration, würde ich mit einer gewissen Reihenfolge beginnen:

{p1, p2, p3, p4, p5}

und eine Sequenz produzieren:

{p2, p3, p4, p5, p1}

Dann zip ich sie zusammen, erstellen ein Liniensegment von den Punkten, die in jeder Sequenz an derselben Position erscheinen.

mit dem obigen Beispiel fortzufahren, eine neue Sequenz aus den Elementen in den beiden zu schaffen, eine beliebige Funktion verwendet:

{f (p1, p2), f (p2, p3), f (p3, p4), f (p4, p5), f (p5, p1)}

wo ist f ist mein geliefert Zipping-Funktion.

Dieser Ansatz erfordert weit weniger Code und führt viel seltener zu Indexierungsfehlern.