2012-06-16 40 views

回答

2

我會用:

indicies[x_] := Reap[MapIndexed[Sow[#2, #] &, x]][[2, All, All, 1]] 

這將是比重複地使用Position,在很長的名單,具有許多獨特元素更快。例如:

list = RandomInteger[9999, 10000]; 

Timing[ 
    result1 = 
    Function[x, ([email protected][x, #] &) /@ DeleteDuplicates[x]]@list; 
] 
{3.463, Null} 
Timing[ 
    result2 = indicies @ list; 
] 
{0.031, Null} 
result1 === result2 
True 

TomD代替SowReap使用較新的GatherBy建議。在長列表中這一點甚至更快,重複性很低。

indicies2[x_] := GatherBy[List ~MapIndexed~ x, First][[All, All, 2, 1]] 

list2 = RandomInteger[99999, 100000]; 

Do[indicies @ list2, {10}] // Timing 
Do[indicies2 @ list2, {10}] // Timing 
{5.523, Null} 

{2.823, Null} 

速度是在列表更大的重複更加相似:

list3 = RandomInteger[99, 100000]; 

Do[indicies @ list3, {10}] // Timing 
Do[indicies2 @ list3, {10}] // Timing 
{1.716, Null} 

{1.607, Null} 

如果打算爲純粹的速度必須認識到,MapIndexed不優化d用於填充陣列,因此RangeTranspose會相當快在這種情況下:

indicies3[x_] := GatherBy[{x, [email protected]@x}\[Transpose], First][[All, All, 2]] 

Do[indicies3 @ list2, {10}] // Timing 
{1.981, Null} 
Do[[email protected], {10}] // Timing (* big difference here *) 
{0.125, Null} 
+1

這兩種方法的執行速度似乎取決於列表的內容。對於長度爲1,000,000的列表,只包含兩個值,「指數」('indices'?)是0.78s比0.71s更慢的一個分數。 –

+2

更加優雅。 'GatherBy [MapIndexed [{#1,#2}&,list],First] [[All,All,2,1]]作爲變體? – tomd

+0

@image_doctor好的,如果「位置」只被稱爲幾次,它將會很快,而且我並不是想要以其他方式暗示。我想我應該說「對於許多獨特的元素」而不是長列表。 –

1

一種可能性:

Function[x, ([email protected][x, #] &) /@ DeleteDuplicates[x]]@{1, 3, 
    3, 7} 

給予

(* {{1}, {2, 3}, {4} *) 

又如:

lst = {1, 3, 3, 3, 7, 4, 3}; 
Function[x, ([email protected][x, #] &) /@ DeleteDuplicates[x]]@lst 

,並提供:

(*{{1}, {2, 3, 4, 7}, {5}, {6}}*) 
相關問題