Dr.*_*ius 10 wolfram-mathematica
我需要建立一个局部的Inverted Index
.就像是:
l = {{x, {h, a, b, c}}, {y, {c, d, e}}}
iI[l]
(*
-> {{a, {x}}, {b, {x}}, {c, {x, y}}, {d, {y}}, {e, {y}}, {h, {x}}}
*)
Run Code Online (Sandbox Code Playgroud)
我认为它的作用非常清楚.在输入列表中,{x,y ...}是唯一的,而{a,b,c,..}则不是.输出应该按顺序排序#[[1]]
.
现在,我这样做:
iI[list_List] := {#, list[[Position[list, #][[All, 1]]]][[All, 1]]} & /@
(Union@Flatten@Last@Transpose@list)
Run Code Online (Sandbox Code Playgroud)
但是对于这么简单的任务看起来太复杂了,看起来太慢了,我应该能够应付军团.
试驾比较你的结果:
words = DictionaryLookup[];
abWords = DictionaryLookup["ab" ~~ ___];
l = {#, RandomChoice[abWords, RandomInteger[{1, 30}]]} & /@ words[[1 ;; 3000]];
First@Timing@iI[l]
(*
-> 5.312
*)
Run Code Online (Sandbox Code Playgroud)
那么,加速的任何想法?
Leo*_*rin 10
似乎是一项经典任务Reap
- Sow
(由于@Heike而改进最终版本):
iI[list_] := Sort[Reap[Sow @@@ list, _, List][[2]]]
Run Code Online (Sandbox Code Playgroud)
然后,
iI[l]
{{a, {x}}, {b, {x}}, {c, {x, y}}, {d, {y}}, {e, {y}}, {h, {x}}}
Run Code Online (Sandbox Code Playgroud)
和
In[22]:=
words=DictionaryLookup[];
abWords=DictionaryLookup["ab"~~___];
l={#,RandomChoice[abWords,RandomInteger[{1,30}]]}&/@words[[1;;3000]];
First@Timing@iI[l]
Out[25]= 0.047
Run Code Online (Sandbox Code Playgroud)
编辑
这是一个具有类似(稍差)性能的替代版本:
iIAlt[list_] :=
Sort@Transpose[{#[[All, 1, 2]], #[[All, All, 1]]}] &@
GatherBy[Flatten[Thread /@ list, 1], Last];
Run Code Online (Sandbox Code Playgroud)
有趣的是Reap
- Sow
这里提供的解决方案比基于结构操作的解决方案更快.
编辑2
只是插图-为那些喜欢谁基于规则的解决方案,下面是基于对一个组合中的一个Dispatch
,并ReplaceList
:
iIAlt1[list_] :=
With[{disp = Dispatch@Flatten[Thread[Rule[#2, #]] & @@@ list]},
Map[{#, ReplaceList[#, disp]} &, Union @@ list[[All, 2]]]]
Run Code Online (Sandbox Code Playgroud)
不过,它比其他两个慢约2-3倍.