2011-11-26 43 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上慢得多。我将在我自己的帖子中添加时间以供参考。 –