2011-10-13 44 views
10

Tôi cần phải xây dựng một phần Inverted Index. Một cái gì đó như:Xây dựng một phần chỉ số đảo ngược thời gian hiệu quả

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}}} 
*) 

Tôi nghĩ rằng nó là khá rõ ràng những gì nó làm. Trong danh sách đầu vào, {x, y ...} là duy nhất, trong khi {a, b, c, ..} thì không. Đầu ra phải được đặt hàng bởi #[[1]].

Ngay bây giờ, tôi đang làm điều này:

iI[list_List] := {#, list[[Position[list, #][[All, 1]]]][[All, 1]]} & /@ 
        ([email protected]@[email protected]@list) 

Nhưng nó có vẻ quá phức tạp cho một nhiệm vụ dễ dàng như vậy, dường như quá chậm, và tôi sẽ có thể đối phó với Legion.

Một lái thử để so sánh kết quả của bạn:

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

Vì vậy, bất kỳ ý tưởng cho một sự tăng tốc?

Trả lời

10

Có vẻ là một nhiệm vụ cổ điển cho Reap-Sow (cải tiến trong phiên bản cuối cùng do @Heike):

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

Sau đó,

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]]; 
[email protected]@iI[l] 
Out[25]= 0.047 

EDIT

Dưới đây là một phiên bản thay thế với một hiệu suất tương tự (hơi xấu):

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

Điều thú vị là Reap-Sow đây đưa ra một giải pháp thậm chí hơi nhanh hơn so với một dựa trên hoạt động cơ cấu.

EDIT 2

Chỉ cần cho một minh hoạ - cho những người thích các giải pháp dựa trên luật lệ, đây là một trong dựa trên sự kết hợp của DispatchReplaceList:

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

Đó là về 2- Tuy nhiên, chậm hơn 3 lần so với hai loại kia.

+1

Một bước để vinh quang http://i.stack.imgur.com/EqlqO.png :) –

+2

Thật vậy. 'Thread'-ing danh sách thậm chí không cần thiết; bạn có thể làm một cái gì đó như 'iI [list_]: = Sắp xếp [Reap [Sow @@@ list, _, List] [[2]]]' để làm cho nó thậm chí còn nhanh hơn. – Heike

+0

@Heike Thật vậy, cảm ơn. Khi tôi đang phát triển mã, tôi bằng cách nào đó đầu tiên nghĩ rằng nó nên được 'gieo [# 2, # 1] &', mà, nếu đúng, yêu cầu 'Thread'. Khi tôi nhận ra lệnh đặt hàng là trực tiếp, tôi quên xóa nó đi. Sẽ chỉnh sửa để sử dụng phiên bản của bạn. –

Các vấn đề liên quan