【发布时间】:2011-05-01 17:29:34
【问题描述】:
我有这个特定的函数来提取列表的一部分,格式为:Give[list, elem] 返回 list 中对应于全局中 elem 位置的部分$Reference 变量(如果已定义)。我在我的代码中大量使用了这个函数,所以我决定优化它。到目前为止,这是我设法到达的地方,但坦率地说,我不知道如何前进。
ClearAll[Give, $Reference, set];
Give::noref = "No, non-list or empty $Reference was defined to refer to by Give.";
Give::noelem = "Element (or some of the elements in) `1` is is not part of the reference set `2`.";
Give::nodepth = "Give cannot return all the elements corresponding to `1` as the list only has depth `2`.";
give[list_, elem_List, ref_] := Flatten[Pick[list, ref, #] & /@ elem, 1];
give[list_, elem_, ref_] := First@Pick[list, ref, elem];
Options[Give] = {Reference :> $Reference}; (* RuleDelayed is necessary, for it is possible that $Reference changes between two subsequent Give calls, and without delaying its assignment, ref would use previous value of $Reference instead of actual one. *)
Give[list_List, elem___, opts___?OptionQ] := Module[{ref, pos},
ref = Reference /. {opts} /. Options@Give;
Which[
Or[ref === {}, Head@ref =!= List], Message[Give::noref]; {},
Complement[Union@Flatten@{elem}, ref] =!= {}, Message[Give::noelem, elem, ref]; {},
Length@{elem} > Depth@list - 1, Message[Give::nodepth, {elem}, Depth@list]; {},
True, Fold[give[#1, #2, ref] &, list, {elem}]
]];
In[106]:= $Reference = {"A", "B", "C"};
set = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
Give[set, "B"](* return specified row *)
Out[108]= {4, 5, 6}
In[109]:= Give[set, "B", "A"] (* return entry at specified row & column *)
Out[109]= 4
In[110]:= Give[set, {"B", "A"}] (* return multiple rows *)
Out[110]= {{4, 5, 6}, {1, 2, 3}}
我决定放弃不同的签名函数调用,因为列表版本可能会调用非列表版本,这意味着必须多次进行错误处理(对于列表中的每个元素)。遗憾的是,错误处理不能被丢弃。如果改进后的版本更健壮(例如可以处理更多维度),那不是问题,但是上面的示例就足够了。
In[139]:= First@Timing[Give[set, RandomChoice[$Reference, 10000]]] (* 1D test *)
Out[139]= 0.031
In[138]:= First@Timing[Table[Give[set, Sequence @@ RandomChoice[$Reference, 2]], {10000}]] (* 2d test *)
Out[138]= 0.499
我确信这不是有效的代码,所以请随时改进它。任何帮助都表示赞赏,即使它只减少了几纳秒。
【问题讨论】:
-
István,您对我们的回答有何看法?
-
请原谅,我没有忘记评估您的解决方案,但目前我正忙于写我的论文。早期结果表明,由于我的代码中的特定调用,这两种解决方案都不能产生相当大的时间增益,所以我立即放弃了这条路线以加快我的模拟速度。在我有更多时间再次深入研究之前,我不会对此事做出结论。请耐心等待。
-
我明白了。我希望你的论文顺利。
标签: optimization wolfram-mathematica