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

时间:2011-10-13 04:59:29

标签: 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}}}
*)

我认为它的作用非常清楚。在输入列表中,{x,y ...}是唯一的,而{a,b,c,..}则不是。输出应按#[[1]]排序。

现在,我这样做:

iI[list_List] := {#, list[[Position[list, #][[All, 1]]]][[All, 1]]} & /@ 
                     (Union@Flatten@Last@Transpose@list)

但是对于这么简单的任务看起来太复杂了,似乎太慢了,我应该能够应付军团。

用于比较结果的试驾:

words = DictionaryLookup[];
abWords = DictionaryLookup["ab" ~~ ___];
l = {#, RandomChoice[abWords, RandomInteger[{1, 30}]]} & /@ words[[1 ;; 3000]];
First@Timing@iI[l]
(*
-> 5.312
*)

那么,有关加速的想法吗?

1 个答案:

答案 0 :(得分:10)

似乎Reap的一项经典任务 - Sow(由于@Heike而在最终版本中有所改进):

iI[list_] := Sort[Reap[Sow @@@ list, _, List][[2]]] 

然后,

iI[l]

{{a, {x}}, {b, {x}}, {c, {x, y}}, {d, {y}}, {e, {y}}, {h, {x}}}

In[22]:= 
words=DictionaryLookup[];
abWords=DictionaryLookup["ab"~~___];
l={#,RandomChoice[abWords,RandomInteger[{1,30}]]}&/@words[[1;;3000]];
First@Timing@iI[l]
Out[25]= 0.047

修改

以下是具有类似(稍差)性能的替代版本:

iIAlt[list_] :=
   Sort@Transpose[{#[[All, 1, 2]], #[[All, All, 1]]}] &@
           GatherBy[Flatten[Thread /@ list, 1], Last];

有趣的是,Reap - Sow提供的解决方案比基于结构操作的解决方案更快。

编辑2

仅为了说明 - 对于那些喜欢基于规则的解决方案的人来说,这里有一个基于DispatchReplaceList的组合:

iIAlt1[list_] :=
   With[{disp = Dispatch@Flatten[Thread[Rule[#2, #]] & @@@ list]},
       Map[{#, ReplaceList[#, disp]} &, Union @@ list[[All, 2]]]]

然而,它比其他两个慢约2-3倍。