2011-11-26 45 views
8

我對Mathematica很陌生,很難被這個問題困擾。我有一個如下所示的列表:用子列表中的第一項代替子列表

{{1, 1, 1}, {0}, {1}} 

我想用它的第一個元素替換每個子列表。所以,上面的列表應該轉換爲:

{1,0,1} 

我已經瀏覽了多次文檔,並Google搜索幾個小時。我相信這很簡單,但我無法弄清楚。我開始與這個名單:

{1, 1, 1, 0, 1} 

我需要知道有多少的1的運行也有,這顯然是2。所以,我用斯普利特清單分成連續的1和0的組。通過在這個列表上使用Length,我可以得到總運行次數,它是3.現在,我只需要計算1的運行次數。如果我可以像上面提到的那樣轉換列表,我可以將列表中的項目相加以得到答案。

我希望這是有道理的。謝謝你的幫助!

回答

6

我應該這樣做:

Count[Split[{1, 1, 1, 0, 1}][[All, 1]], 1] 

Total[First /@ Split[{1, 1, 1, 0, 1}]] 
+0

完美,非常感謝!我試過[All,1]訪問子列表,但我無法弄清楚要計數的模式。所以,模式只是1,對吧? –

+1

是的,在這種情況下,模式是文字1. –

6

另一種方法,使用Count尋找含有一定數目的1重複的名單:

In[20]:= Count[Split[{1, 1, 1, 0, 1}], {1 ..}] 

Out[20]= 2 
+0

謝謝佈雷特。我發誓我嘗試了一些非常接近的事情,但我一直在模式上發現錯誤。由於您的解決方案有效,我顯然出現了問題。 –

12

的提出的解決方案非常快,但是如果你想要極高的效率(巨大的列表),她e是另一個這將是數量級快(配製爲純函數):

Total[Clip[[email protected]#,{0, 1}]] + First[#] & 

例如:

In[86]:= 
largeTestList = RandomInteger[{0,1},{10^6}]; 
Count[Split[largeTestList],{1..}]//Timing 
Count[Split[largeTestList][[All,1]],1]//Timing 
Total[Clip[[email protected]#,{0, 1}]] + First[#] &@largeTestList//Timing 

Out[87]= {0.328,249887} 
Out[88]= {0.203,249887} 
Out[89]= {0.015,249887} 

EDIT

沒indend以引發「大槍戰」,但是當我們在這個時候,讓我把最大的炮編譯成C:

runsOf1C = 
Compile[{{lst, _Integer, 1}}, 
    Module[{r = Table[0, {Length[lst] - 1}], i = 1, ctr = First[lst]}, 
    For[i = 2, i <= Length[lst], i++, 
     If[lst[[i]] == 1 && lst[[i - 1]] == 0, ctr++]]; 
     ctr], 
    CompilationTarget -> "C", RuntimeOptions -> "Speed"] 

現在,

In[157]:= 
hugeTestList=RandomInteger[{0,1},{10^7}]; 
Total[Clip[ListCorrelate[{-1,1},#],{0,1}]]+First[#]&@hugeTestList//AbsoluteTiming 
runsOf1C[hugeTestList]//AbsoluteTiming 

Out[158]= {0.1872000,2499650} 
Out[159]= {0.0780000,2499650} 

當然,這不是一個完美的解決方案,但它很簡單。

編輯2

提高上@Sjoerd的優化,這將是一個大約1。5快於runsOf1C仍然:

runsOf1CAlt = 
Compile[{{lst, _Integer, 1}}, 
    Module[{r = Table[0, {Length[lst] - 1}], i = 1, ctr = First[lst]}, 
    For[i = 2, i <= Length[lst], i++, 
    If[lst[[i]] == 1, 
     If[lst[[i - 1]] == 0, ctr++]; 
     i++ 
    ]]; 
    ctr], 
    CompilationTarget -> "C", RuntimeOptions -> "Speed"] 
+2

Oooh,聰明...你可以通過使用'Tr'而不是'Total'來獲得更多的速度。 (在我的Mac上爲20%)。 –

+0

絕對聰明。 – rcollyer

+0

令人印象深刻。太多以至於我不得不研究它來弄清它是如何工作的。幸運的是,我的名單不會超過幾千件。 –

7

這裏是列昂尼德的Differences方法的變型即稍快是:(使用Tr爲兩者)

([email protected]@[email protected]# + [email protected]#[[{1,-1}]])/2 & 

相比:

list = RandomInteger[1, 1*^7]; 

Tr[Clip[[email protected]#, {0,1}]] + First[#] & @ list //timeAvg 

([email protected]@[email protected]# + [email protected]#[[{1,-1}]])/2 & @ list //timeAvg 
0.1186
0.0904

由於這已經成爲一個代碼效率的競爭,這是我未來的努力:使用Mathematica 7

([email protected][[email protected]#, [email protected]#] + [email protected]#[[{1, -1}]])/2 & 

而且,我得到非常不同的結果,所以我在這裏包括它們以供參考:

largeTestList = RandomInteger[{0, 1}, {10000000}]; 
Count[Split[largeTestList], {1 ..}] // AbsoluteTiming 
Count[Split[largeTestList][[All, 1]], 1] // AbsoluteTiming 
Total[Clip[[email protected]#, {0, 1}]] + First[#] &@largeTestList // AbsoluteTiming 
([email protected]@[email protected]# + [email protected]#[[{1, -1}]])/2 &@largeTestList // AbsoluteTiming 
Total[Clip[ListCorrelate[{-1, 1}, #], {0, 1}]] + First[#] &@largeTestList // AbsoluteTiming 
([email protected][[email protected]#, [email protected]#] + [email protected]#[[{1, -1}]])/2 &@largeTestList // AbsoluteTiming 

{1.3400766, 2499840} 

{0.9670553, 2499840} 

{0.1460084, 2499840} 

{0.1070061, 2499840} 

{0.3710213, 2499840} 

{0.0480028, 2499840} 
+0

+1我其實認爲這樣的事情應該是可能的,但不夠持久:)。 –

+0

我想ListMorrelate必須在mma 8中得到改進。 –

+0

@Sjoerd,我的BitXor方法在你的機器上如何比較? –

8

你實際上有兩個問題,一個來自標題和隱藏在它後面的問題。第一種是通過回答:

First/@ list 

第二個,計數1的遊程的數量,已經回答了很多次,但是這種解決方案

Total[Clip[ListCorrelate[{-1, 1}, #], {0, 1}]] + First[#] & 

比獅子座的解決方案快大約50% 。注意:我增加了測試列表的長度爲更好的時機:

largeTestList = RandomInteger[{0, 1}, {10000000}]; 
Count[Split[largeTestList], {1 ..}] // AbsoluteTiming 
Count[Split[largeTestList][[All, 1]], 1] // AbsoluteTiming 
Total[Clip[[email protected]#, {0, 1}]] + First[#] &@ largeTestList // AbsoluteTiming 
([email protected]@[email protected]# + [email protected]#[[{1, -1}]])/2 &@ largeTestList // AbsoluteTiming 
Total[Clip[ListCorrelate[{-1, 1}, #], {0, 1}]] + First[#] &@ 
    largeTestList // AbsoluteTiming 


Out[680]= {3.4361965, 2498095} 

Out[681]= {2.4531403, 2498095} 

Out[682]= {0.2710155, 2498095} 

Out[683]= {0.2530145, 2498095} 

Out[684]= {0.1710097, 2498095} 

獅子座的編譯攻擊後,我正要在認輸,但我發現了一個可能的優化,所以開始進入戰鬥.. [Mr.Wizard,獅子座和我應該在監獄裏被拋出干擾對SO和平]

runsOf1Cbis = 
Compile[{{lst, _Integer, 1}}, 
    Module[{r = Table[0, {Length[lst] - 1}], i = 1, ctr = First[lst]}, 
    For[i = 2, i <= Length[lst], i++, 
    If[lst[[i]] == 1 && lst[[i - 1]] == 0, ctr++; i++]]; 
    ctr], CompilationTarget -> "C", RuntimeOptions -> "Speed"] 

largeTestList = RandomInteger[{0, 1}, {10000000}]; 
Total[Clip[ListCorrelate[{-1, 1}, #], {0, 1}]] + First[#] &@ 
    largeTestList // AbsoluteTiming 
runsOf1C[largeTestList] // AbsoluteTiming 
runsOf1Cbis[largeTestList] // AbsoluteTiming 


Out[869]= {0.1770101, 2500910} 

Out[870]= {0.0960055, 2500910} 

Out[871]= {0.0810046, 2500910} 

結果各不相同,但我得到10和30%之間的改善。

優化可能很難發現,但如果{0,1}測試成功,則是額外的i++。在連續的地點你不能有兩個。


而且,在這裏,我自己的優化優化的列昂尼德的優化優化(我希望這不會拖,或者我要去挨一個堆棧溢出):

runsOf1CDitto = 
Compile[{{lst, _Integer, 1}}, 
    Module[{i = 1, ctr = First[lst]}, 
    For[i = 2, i <= Length[lst], i++, 
    If[lst[[i]] == 1, If[lst[[i - 1]] == 0, ctr++]; 
    i++]]; 
    ctr], CompilationTarget -> "C", RuntimeOptions -> "Speed"] 

largeTestList = RandomInteger[{0, 1}, {10000000}]; 
Total[Clip[ListCorrelate[{-1, 1}, #], {0, 1}]] + First[#] &@ 
    largeTestList // AbsoluteTiming 
runsOf1C[largeTestList] // AbsoluteTiming 
runsOf1Cbis[largeTestList] // AbsoluteTiming 
runsOf1CAlt[largeTestList] // AbsoluteTiming 
runsOf1CDitto[largeTestList] // AbsoluteTiming 


Out[907]= {0.1760101, 2501382} 

Out[908]= {0.0990056, 2501382} 

Out[909]= {0.0780045, 2501382} 

Out[910]= {0.0670038, 2501382} 

Out[911]= {0.0600034, 2501382} 

幸運的是,列昂尼德在他的代碼中有一個多餘的初始化,可以刪除。

+1

+1。我不知道有什麼比「差異」更快,後者本質上是「休息[#] - 大多數[#]&'。今天學到了一些新東西:) –

+0

同上獅子座說什麼。我必須非常聰明才能打敗他。 :-)(順便說一句,我很驚訝兩種'差異'方法之間沒有更多的差異;我的系統上有這種差異。) –

+1

實際上,你的方法在v7上慢得多。我將在我自己的帖子中添加時間以供參考。 –