Frage

Bitte beachten Sie:

daList = {{{21, 18}, {20, 18}, {18, 17}, {20, 15}}, 
          {{21, 18}, {20, 18}, {21, 14}, {21, 14}}};

Ich möchte den Abstand zwischen jedem Punkt in den 2 Unterlisten dieser Liste berechnen:

Ich muss jedoch einen Function verwenden, um auf der richtigen Ebene anzuwenden:

Function[seqNo, 
         EuclideanDistance[#, {0, 0}] & /@ daList[[seqNo]]] /@ 
         Range[Length@daList]

out = {{3 Sqrt[85], 2 Sqrt[181], Sqrt[613], 25}, {3 Sqrt[85], 2 Sqrt[181], 
        7 Sqrt[13], 7 Sqrt[13]}}

Gibt es eine Möglichkeit, diese schwere Funktion dort zu vermeiden? Um die Ebene anzugeben, die meine Funktion mit seqNo als Argument vermeidet?:

EuclideanDistance[#, {0, 0}] & /@ daList

out={EuclideanDistance[{{21, 18}, {20, 18}, {18, 17}, {20, 15}}, {0, 0}], 
     EuclideanDistance[{{21, 18}, {20, 18}, {21, 14}, {21, 14}}, {0, 0}]}

War es hilfreich?

Lösung

Haben Sie die Level-Spezifikation in Map ausprobiert?

Map[EuclideanDistance[#, {0, 0}] &, daList, {2}]

gibt

{{3 Sqrt[85],2 Sqrt[181],Sqrt[613],25},{3 Sqrt[85],2 Sqrt[181],7 Sqrt[13],7 Sqrt[13]}}

Andere Tipps

Um die Antwort von @Markus zu ergänzen: Wenn Ihr daList sehr groß und numerisch ist, ist Folgendes viel schneller (wie 30x), wenn auch etwas weniger allgemein:

Sqrt@Total[daList^2,{3}]

Hier ist ein Beispiel:

In[17]:= largeDaList = N@RandomInteger[30,{100000,4,2}];
In[18]:= Map[EuclideanDistance[#,{0,0}]&,largeDaList,{2}]//Short//Timing
Out[18]= {0.953,{{31.7648,34.6699,20.3961,31.305},<<99998>>,{<<18>>,<<2>>,0.}}}

In[19]:= Sqrt@Total[largeDaList^2,{3}]//Short//Timing
Out[19]= {0.031,{{31.7648,34.6699,20.3961,31.305},<<99998>>,{<<18>>,<<2>>,0.}}}

Der Grund dafür ist, dass Funktionen wie Power und Sqrt Listable sind und Sie die Iteration in den Kernel verschieben. Funktionen wie Map können die zugeordnete Funktion in vielen Fällen auch automatisch kompilieren, in diesem Fall jedoch anscheinend nicht.

EDIT

Auf Anfrage des OP folgt eine Verallgemeinerung auf den Fall eines nicht trivialen Bezugspunkts:

refPoint = {3, 5};
Sqrt@Total[#^2, {3}] &@Transpose[Transpose[daList, {3, 2, 1}] - refPoint, {3, 2, 1}]

Es ist immer noch schnell, aber nicht so präzise wie zuvor. Zum Vergleich ist hier der Code, der auf Maping basiert und hier nur geringfügig geändert werden muss:

Map[EuclideanDistance[#, refPoint] &, daList, {2}]

Der Leistungsunterschied bleibt in der gleichen Größenordnung, obwohl sich die vektorisierte Lösung aufgrund der Notwendigkeit nicht trivialer Transpositionen etwas verlangsamt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top