500*_*500 2 wolfram-mathematica euclidean-distance
请考虑:
daList = {{{21, 18}, {20, 18}, {18, 17}, {20, 15}},
{{21, 18}, {20, 18}, {21, 14}, {21, 14}}};
Run Code Online (Sandbox Code Playgroud)
我想计算该列表的2个子列表中每个点之间的距离:
但我需要使用a Function来应用于正确的级别:
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]}}
Run Code Online (Sandbox Code Playgroud)
有没有办法避免这种繁重的功能呢?使用seqNo作为参数指定避免我的函数的级别?:
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}]}
Run Code Online (Sandbox Code Playgroud)
你在Map中尝试过Level规范吗?
Map[EuclideanDistance[#, {0, 0}] &, daList, {2}]
Run Code Online (Sandbox Code Playgroud)
给
{{3 Sqrt[85],2 Sqrt[181],Sqrt[613],25},{3 Sqrt[85],2 Sqrt[181],7 Sqrt[13],7 Sqrt[13]}}
Run Code Online (Sandbox Code Playgroud)
为了补充@Markus的答案:如果你的daList数字非常庞大且数值很大,那么下面会更快(比如30x),尽管有些不那么普遍:
Sqrt@Total[daList^2,{3}]
Run Code Online (Sandbox Code Playgroud)
这是一个例子:
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.}}}
Run Code Online (Sandbox Code Playgroud)
原因是函数喜欢Power和Sqrt是Listable,并且您将迭代推送到内核中.类似Map的函数在很多情况下也可以自动编译映射函数,但显然不是这种情况.
编辑
根据OP的要求,这里是对非平凡参考点的概括:
refPoint = {3, 5};
Sqrt@Total[#^2, {3}] &@Transpose[Transpose[daList, {3, 2, 1}] - refPoint, {3, 2, 1}]
Run Code Online (Sandbox Code Playgroud)
它仍然很快,但不像以前那么简洁.为了比较,这里是基于Map-ping 的代码,这里只需要一个简单的修改:
Map[EuclideanDistance[#, refPoint] &, daList, {2}]
Run Code Online (Sandbox Code Playgroud)
性能差异保持相同的数量级,尽管矢量化解决方案由于需要非平凡的转置而减慢一点.