2011-11-26 4 views
8

저는 Mathematica를 처음 접했고이 문제로 난처한 상황에 처했습니다. 다음과 같은 목록이 있습니다 :하위 목록을 하위 목록의 첫 번째 항목으로 바꾸기

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

각 하위 목록을 첫 번째 요소로 바꾸고 싶습니다. 위 목록은 다음과 같이 변환해야합니다.

{1,0,1} 

저는 문서를 반복적으로 살펴보고 몇 시간 씩 인터넷을 검색했습니다. 나는 이것이 매우 간단하다고 확신하지만, 나는 그것을 이해할 수 없다. 나는이 목록 시작 :

{1, 1, 1, 0, 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

완벽한, 정말 고마워요! 내가 [전체, 1] 하위 목록에 액세스하려고했는데, 나는 셀 수있는 패턴을 알아낼 수 없었다. 그래서 패턴은 단순히 1입니다. 맞습니까? –

+1

예,이 경우 패턴은 리터럴 1입니다. –

6

또 다른 방법을 하나의 반복 몇 가지 숫자를 포함하는 목록을 찾아 Count를 사용하여 :

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

Out[20]= 2 
+0

감사합니다. 나는 그 일에 아주 근접해있는 것을 시도했다고 맹세한다. 나는 분명히 당신의 솔루션이 작동하기 때문에 잘못된 것이있었습니다. –

12

제안 된 솔루션은 매우 빠르지 만 극단적 인 효율성 (거대한 목록)을 원한다면 예를 들어

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

: 나는을 시작 indend하지 않았다

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 전자는 (순수 함수로 공식화) 크기의 순서 빠른 것 또 다른 하나입니다 "큰 총격전"그러나 우리가 그것에있는 동안, 내가 가장 큰 총을 잡아 당겨 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"] 
이제 10

물론

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이됩니다.(모두 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
여기
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, clever ... 'Total'대신 'Tr'을 사용하면 속도를 조금 더 높일 수 있습니다. (내 Mac에서는 20 %) –

+0

확실히 똑똑합니다. – rcollyer

+0

인상적입니다. 너무 많이 그래서 어떻게 작동하는지 알아 내기 위해 그것을 연구해야 할 것입니다. 다행히도 내 목록은 수천 개의 항목을 초과하지 않을 것입니다. –

7

약간 빠르다 레오 니드의 Differences 방법의 변형이다 : 5 빠른 여전히 runsOf1C보다
0.0904
매스 매 티카 7을 사용 또한

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

, 내가 얻고 매우 다른 결과, 그래서 참조를 위해 여기를 포함하고있다 :이 이후


210 여기 내 옆에 노력, 코드 효율 경쟁이되었다

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

ListCorrelate가 mma 8에서 개선되었을 것입니다. –

+0

@Sjoerd, BitXor 메서드를 컴퓨터에서 어떻게 비교합니까? –

8

실제로 두 가지 질문이 있습니다. 그 중 하나는 제목과 그 뒤에 숨어있는 질문입니다. 첫 번째는 응답 : 1의의 실행의 수를 계산,

First/@ list 

두 번째, 여러 번 대답하지만,이 솔루션

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} 

레오 니드의 컴파일 공격 후 내가 항복하려고했지만, 나는 가능한 최적화를 발견, 그래서 이후 전투를 간다 .. . 결과는 다를

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} 

[Mr.Wizard, 레오 니드 나는 SO의 평화를 방해 감옥에 던져해야한다, 그러나 나는 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} 

나를 위해 운좋게도, Leonid는 제거 될 수있는 코드에서 불필요한 초기화 작업을 수행했습니다.

+1

+1을 모두 확인하십시오. 후자는 본질적으로'Rest [#] - Most [#] &'입니다. 오늘 새로운 무언가를 배웠습니다 :) –

+0

레오 니드가 말한 것과 마찬가지입니다. 나는 그것을 치기 위해 정말로 영리해야만 할 것이다. :-) (BTW, 두 Differences 메서드 사이에 차이가 없다는 것에 놀랍니다. 내 시스템에 있습니다.) –

+1

사실, 메서드가 v7에서 훨씬 느립니다. 참조 용으로 자신의 게시물에 타이밍을 추가 할 예정입니다. –

관련 문제