4
$\begingroup$

How do I apply a function (this case EuclideanDistance) between element i and i+1 on a list with points?

It should return a new list that is one element shorter than the input list.

$\endgroup$
  • 8
    $\begingroup$ EuclideanDistance @@@ Partition[list, 2, 1]? Alternatively, Norm /@ Differences[list]? $\endgroup$ – J. M. will be back soon May 31 '15 at 7:39
  • $\begingroup$ Thank you! I guess it was so basic so it was not easy to find in documentation. :-) $\endgroup$ – bjornrun May 31 '15 at 7:45
  • $\begingroup$ Possible duplicate: 4061 $\endgroup$ – shrx May 31 '15 at 14:43
7
$\begingroup$
nPoints = 9;
lst = RandomReal[{-1, 1}, {nPoints, 3}];
lst = Partition[lst, {2}, 1]
EuclideanDistance[First[#], Last[#]] & /@ lst

ps. after posting saw Guesswhoitis above. I think using @@@ is nicer there. I used simple Mapping to do the job. So for completion, a less typing solution is as shown above by Guesswhoitis which is

 EuclideanDistance @@@ Partition[list, 2, 1]  (*not my code, see comment above*)
$\endgroup$
  • $\begingroup$ Why not edit your answer to include it? :) $\endgroup$ – J. M. will be back soon May 31 '15 at 8:11
  • $\begingroup$ @Guesswhoitis. ok, for completion, I also added your solution. thanks $\endgroup$ – Nasser May 31 '15 at 8:18
4
$\begingroup$
f0 = EuclideanDistance @@@ Partition[#, 2, 1] &; (* Nasser's post*)
f1 = Norm /@ Differences@# &; (* Guesswhoitis's comment *)
f2 = Compose[EuclideanDistance @@@ # &, Partition[#, 2, 1] &, #] &;
f3 = Composition[EuclideanDistance @@@ # &, Partition[#, 2, 1] &];
f4 = Developer`PartitionMap[EuclideanDistance @@ # &, #, 2, 1] &;
f5 = Table[EuclideanDistance @@ #[[{i, i + 1}]], {i, Length[#] - 1}] &;
f6 = EuclideanDistance @@@ Transpose[{Most@#, Rest@#}] &;
f7 = Thread[foo[Most@#, Rest@#]] /. foo -> EuclideanDistance & ;
f8 = MapThread[EuclideanDistance, {Most@#, Rest@#}] &;
f9 = MapThread[EuclideanDistance, Transpose@Partition[#, 2, 1]] &;
funcs = {f0, f1, f2, f3, f4, f5, f6, f7, f8, f9};
labels = {"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9"};

SeedRandom[3210]
lst = RandomReal[{-1, 1}, {10, 3}];
Equal @@ (Through@funcs@lst)
(* True *)

Timings:

SeedRandom[3210]
testlst1 = RandomReal[{-1, 1}, {100000, 3}];
res = ConstantArray[0, 10];
i = 1;
timings1 = First[AbsoluteTiming[res[[i++]] = #@testlst1]] & /@ funcs;
Equal @@ res

True

testlst2 = RandomReal[{-1, 1}, {1000000, 3}];
res = ConstantArray[0, 10];
i = 1;
timings2 = First[AbsoluteTiming[res[[i++]] = #@testlst2]] & /@ funcs;
Equal @@ res

True

Grid[Join[{{"",  "Function", Column[{"Timings", "Sample size"}, Alignment -> Center], 
    SpanFromLeft}}, {{SpanFromAbove, SpanFromAbove, "100 000", "1 000 000"}}, 
 Transpose[{labels, funcs, timings1, timings2}]], 
 Dividers -> All, ItemStyle -> {Automatic, {Automatic, Automatic, Directive[Bold, Red]}}]

enter image description here

Variations:

legendF = With[{pairs = Developer`PartitionMap[{#, EuclideanDistance@@#} &@# &, #, 2, 1]}, 
 Grid[Join[{{"pair", "points", "distance"}}, 
   MapIndexed[{First@#2, #[[1]], #[[2]]} &, {Column[#1], #2} & @@@ pairs]], 
  Dividers -> All]] &;

g3dF = With[{ed = EuclideanDistance @@ #}, {Hue[RandomReal[]], 
         Arrowheads[{(1/25) ed}] , Arrow[Tube[#, (1/50) ed]]}] &;

g3d = Graphics3D[{Sphere[#, .05] & /@ lst, 
    Developer`PartitionMap[g3dF, lst, 2, 1]}, ImageSize -> 400];
legend = legendF@lst // Style[#, 16] &;

Legended[g3d, legend]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.