时间有效的部分倒置索引构建

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倍.

  • 确实不错.列表中的"线程"甚至不是必需的; 你可以做一些像`iI [list_]:=排序[Reap [Sow @@@ list,_,List] [[2]]]`来使它更快. (2认同)
  • 实际上@belisarius,荣耀的两个步骤:)一个答案是工具包CW一个.如果他不断删除他的答案,那只会让列昂尼德更长;) (2认同)