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$
3
  • 8
    $\begingroup$ EuclideanDistance @@@ Partition[list, 2, 1]? Alternatively, Norm /@ Differences[list]? $\endgroup$ May 31, 2015 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, 2015 at 7:45
  • $\begingroup$ Possible duplicate: 4061 $\endgroup$
    – shrx
    May 31, 2015 at 14:43

2 Answers 2

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$
2
  • $\begingroup$ Why not edit your answer to include it? :) $\endgroup$ May 31, 2015 at 8:11
  • $\begingroup$ @Guesswhoitis. ok, for completion, I also added your solution. thanks $\endgroup$
    – Nasser
    May 31, 2015 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 and acknowledge you have read our privacy policy.

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