# Order items by closest to the previous

I have a list of 2D points (a table, imagine the data of a parametric plot shuffled)

I would like to join the points with a line that starts from one of them and always goes to the closest one.

I tried therefore to sort the points doing the following:

• take out the first element,
• search the closest in the remaining list
• bring it to the front
• recurse

so that I can then use ListLinePlot

As a first step I tried to do it in 1D (yes, in this case a simple sorting is sufficient, but not in the 2D case)

However,I have a problem, because I do not know how to specify that a variable IS a list.

Concretely

BringToFront =
Function[{list, pos}, Prepend[list[[pos]], Drop[list, {pos}]]]

BringClosestToFront =
Fuction[{list, val},
BringToFront[list, Nearest[list ->Automatic, val]]]

Follow[{}] = {};
Follow[list] =
Prepend[list[[1]],
Follow[BringClosestToFront[Drop[list, 1], list[[1]]]]]


And the BringClosestToFront is not accepted, with a

Part::partd: Part specification list[[1]] is longer than depth of object. >>


I am also worried of the speed of this recursive solution. Do you thing there may be a way to specify it in a more procedural way (i.e. implement insertion-sort)?

• Prepend and Append based solution can indeed become comparatively slow... Jan 8, 2013 at 9:00
• An alternate style to define functions, using set delayed, is: f[x_List,pos_Integer]:=x[[pos]]. Jan 8, 2013 at 11:08
• This is not what you asked for, but, in case it suits your final objectives better, have you checked FindShortestTour?
– Rojo
Jan 8, 2013 at 14:10
• For some ideas you can check this previous thread or [this related MathGroup post][forums.wolfram.com/mathgroup/archive/2011/Mar/msg00529.html] Jan 8, 2013 at 14:32

FindShortestTour can solve your problem. You need only choose the greedy algorithm. For example, using the same data as image_doctor:

SeedRandom[6];
data = RandomReal[{-10, 10}, {10, 2}];

FindShortestTour[data, Method -> "Greedy"]


{61.2702, {1, 7, 2, 3, 6, 4, 10, 5, 9, 8}}

Show[
Graphics[{Line[data[[{1, 7, 2, 3, 6, 4, 10, 5, 9, 8}]]],
PointSize[Medium], Red, Point[data]}],
ImageSize -> Small]


BTW, the graphics output was generated for me by V9's predictive interface. I didn't write any code for it at all.

Here is another recursive solution based on Nest using an index to the point in the list from which to start.

order[points_List, index_Integer] :=
Nest[With[{elem = Nearest[Last@#, Last@First@#]},
{Join[First@#,elem], DeleteCases[Last@#, elem]}] &,
{{points[[index]]}, Drop[points, {index}]}, Length@points - 1] // First


It looks more complicated than it actually is ( I know that a more concise implementation is out there ). It begins with a list of the form, {{start point},{other points}}. Then moves the nearest point from other points onto the end of the start point list. It continues using the last element of the extended list to find the nearest element in the list of remaining points.

Using BG's data:

ListLinePlot@order[data, 1]


ListLinePlot@order[data, 5]


As a guide to speed, 10 thousand elements took around 44 seconds:

SeedRandom[6];
data2 = RandomReal[{-10, 10}, {10^4, 2}];

Timing[order[data2, 1];]


{43.8883, Null}

A less readable version which maintains duplicate points and is around 20+% faster is as follows:

order[points_, index_] :=
Nest[With[{p =
First@Position[Last@#,
First@Nearest[Last@#, Last@First@#]]}, {Join[First@#,
Take[Last@#, p]], Drop[Last@#, p]}] &, {{points[[index]]},
Drop[points, {index}]}, Length@points - 1] // First

• You have used Length[l] in your code, but l is undefined. I assume this should be Length[points], which may affect the speed estimate. Jan 8, 2013 at 13:07
• @SimonWoods Thanks for that, a cut and paste job that went badly wrong. Jan 8, 2013 at 15:29
• Thank you, I learned a lot of syntax I didn't know from your code! Jan 16, 2013 at 1:49
• @FabioDallaLibera that's very kind of you to say. Good luck. Jan 16, 2013 at 8:37

One simple way :

SeedRandom[6];
data = RandomReal[{-10, 10}, {10, 2}] ;

findNearest[list_, point_] := SortBy[list, EuclideanDistance[#, point] &][[1]]

copy = data;
output = NestList[findNearest[copy = DeleteCases[copy, #], #] &, copy[[1]], Length[copy] - 1];

GraphicsColumn[{ListLinePlot[data], ListLinePlot[output]}]


• Thank you, the NestList as a for loop, and the self assignment (overwrite) inside the function argument are very interesting! Jan 8, 2013 at 9:07
• ok,then I temporarily disable and tick it again later Jan 8, 2013 at 9:09

Here's a version based on a recursively defined function f:

f[{x_, y_}] := f[{x~Join~y[[#]], Drop[y, #]} &@Nearest[y -> Automatic, Last@x]];
f[{x_, {}}] := x;

data = RandomReal[{-10, 10}, {1000, 2}];
output = f[{{First[data]}, Rest[data]}];
ListLinePlot[output, Mesh -> True]


• Thank you for your compact solution! Jan 16, 2013 at 1:50
• This seems to produce the same output as FindShortestTour for the given example and it's faster. Jul 18, 2014 at 6:24