요즘 블로그에 통 글을 안 써와서 거의 폐가와 같이 되어 가고 있었는데요.. ^_^
다름이 아니라, 제가 "이러면 좋겠다!"하고 생각해왔던 바로 그런 성격의 너무 좋은 분을
만나게 되어서 다른 곳에는 신경 쓸 시간이 없었네요. 이히히;
그래도, 1달에 1개 정도는 유지해 두고자;; 쌓아뒀던 코드 단편 하나를 올려 봅니다. 헤헤.
종종 아주 긴 리스트에서 자원관리를 하면서, 자원을 순차탐색으로 할당해야하는 경우가 있습니다.
주로 자원이 직접 사람이 쓰는 것이거나 해서, 순서대로 가는 것이 인지적으로나 쓰고 있는
자리가 모아지는 점에서 유리한 경우에 그런데요. 도서관 같은 곳에서 좌석을 배정한다거나,
DHCP서버에서 IP 주소를 나눠준다거나, 순차적으로 나눠주는 큐 관리 시스템에서 작업을
나눠줄 빈 큐를 찾는다거나 생각보다 제법 많습니다.
이런 경우에, 10번째부터 순차검색하기 시작했으면 끝까지 돈 다음에 처음부터 9번째까지 돌아야
하는 것이 중심원리(?)인데요. 구현하는 방법은 물론 클래스 인스턴스가 최근 찾은 인덱스를
변수로 들고 있다가 그 인덱스부터 끝까지 한 번 돌리고, 처음부터 시작한 인덱스까지 다시
돌리는 방법이 가장 평범하겠습니다. 완전 순서대로 배정할 필요는 없고 대충만 맞으면 되는
경우다 싶으면, FIFO 큐 같은 것도 괜찮은데, 이걸 쓰면 시간이 지날 수록 여기저기 듬성 듬성
나와서 원래 목적과는 달라질 수도 있고요~
그래서 range 2번 돌리는 폼 안 나는(?) 코드 대신 보통 끊임없는 이터레이터에서 개수 제한하는
트릭으로 많이 쓰이는 zip을 섞어서 이렇게 하면 비교적 폼 나게(;;) 연속 검색이 가능한
순차검색이 되겠습니다~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<span class=“kn”>from</span> <span class=“nn”>itertools</span> <span class=“kn”>import</span> <span class=“n”>izip</span><span class=“p”>,</span> <span class=“n”>cycle</span>
<span class=“k”>def</span> <span class=“nf”>contiters</span><span class=“p”>(</span><span class=“n”>L</span><span class=“p”>):</span>
<span class=“n”>cycleiter</span> <span class=“o”>=</span> <span class=“n”>cycle</span><span class=“p”>(</span><span class=“n”>L</span><span class=“p”>)</span>
<span class=“k”>return</span> <span class=“k”>lambda</span><span class=“p”>:</span> <span class=“p”>(</span><span class=“n”>elem</span> <span class=“k”>for</span> <span class=“n”>elem</span><span class=“p”>,</span> <span class=“n”>_</span> <span class=“ow”>in</span> <span class=“n”>izip</span><span class=“p”>(</span><span class=“n”>cycleiter</span><span class=“p”>,</span> <span class=“n”>L</span><span class=“p”>))</span>
<span class=“c”># 여기부터는 테스트</span>
<span class=“n”>itgen</span> <span class=“o”>=</span> <span class=“n”>contiters</span><span class=“p”>(</span><span class=“s”>'abcdef'</span><span class=”p”>)</span>
<span class=“n”>g</span> <span class=“o”>=</span> <span class=“n”>itgen</span><span class=“p”>()</span>
<span class=“k”>for</span> <span class=“n”>i</span> <span class=“ow”>in</span> <span class=“nb”>range</span><span class=“p”>(</span><span class=“mf”>3</span><span class=“p”>):</span>
<span class=“n”>print</span> <span class=“n”>g</span><span class=“o”>.</span><span class=“n”>next</span><span class=“p”>(),</span>
<span class=“n”>print</span>
<span class=“n”>g</span> <span class=“o”>=</span> <span class=“n”>itgen</span><span class=“p”>()</span>
<span class=“k”>for</span> <span class=“n”>c</span> <span class=“ow”>in</span> <span class=“n”>g</span><span class=“p”>:</span>
<span class=“n”>print</span> <span class=“n”>c</span><span class=“p”>,</span>
<span class=“k”>if</span> <span class=“n”>c</span> <span class=“o”>==</span> <span class=“s”>'b'</span><span class=”p”>:</span>
<span class=“k”>break</span>
<span class=“n”>print</span>
<span class=“n”>g</span> <span class=“o”>=</span> <span class=“n”>itgen</span><span class=“p”>()</span>
<span class=“k”>for</span> <span class=“n”>c</span> <span class=“ow”>in</span> <span class=“n”>g</span><span class=“p”>:</span>
<span class=“n”>print</span> <span class=“n”>c</span><span class=“p”>,</span>
<span class=“n”>print</span>
|
실행하면 이렇게 나옵니다.
1
2
3
|
a b c
d e f a b
c d e f a b
|
못 찾으면 전체를 한 번 돌고, 찾으면 거기서 중단하면 그 다음에 시작하면 거기서부터 시작합니다~
여기서 종종 마지막으로 돌았던 놈에서부터 다음에 찾을 때 시작하고 싶은 경우가 있는데요. 비슷한 것이 아쉬운 사례로, itertools.takewhile을 쓰면 처음엔 조건이 맞을 때까지 다 가져오는 것은 좋은데, 그 다음 원소를 가지고 오고 싶어서 .next()하면 이미 조건 맞는지 보려고 갖고간 바람에, 조건 안 맞는 것 가져오는 목적으로 그 다음 이터레이터를 쓰지 못하는 것이 엄청 불편합니다.
그래서 전에 찾았던 부분에서 다시 시작하도록 해 보자면~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<span class=“kn”>from</span> <span class=“nn”>itertools</span> <span class=“kn”>import</span> <span class=“n”>izip</span><span class=“p”>,</span> <span class=“n”>cycle</span>
<span class=“k”>def</span> <span class=“nf”>contiters</span><span class=“p”>(</span><span class=“n”>L</span><span class=“p”>):</span>
<span class=“n”>cycleiter</span> <span class=“o”>=</span> <span class=“n”>cycle</span><span class=“p”>(</span><span class=“n”>L</span><span class=“p”>)</span>
<span class=“n”>indicesnonfirst</span> <span class=“o”>=</span> <span class=“nb”>xrange</span><span class=“p”>(</span><span class=“nb”>len</span><span class=“p”>(</span><span class=“n”>L</span><span class=“p”>)</span> <span class=“o”>–</span> <span class=“mf”>1</span><span class=“p”>)</span>
<span class=“k”>def</span> <span class=“nf”>geniter</span><span class=“p”>(</span><span class=“n”>keeping</span><span class=“o”>=</span><span class=“p”>[</span><span class=“n”>cycleiter</span><span class=“o”>.</span><span class=“n”>next</span><span class=“p”>()]):</span>
<span class=“k”>yield</span> <span class=“n”>keeping</span><span class=“p”>[</span><span class=“mf”>0</span><span class=“p”>]</span>
<span class=“k”>for</span> <span class=“n”>elem</span><span class=“p”>,</span> <span class=“n”>_</span> <span class=“ow”>in</span> <span class=“n”>izip</span><span class=“p”>(</span><span class=“n”>cycleiter</span><span class=“p”>,</span> <span class=“n”>indicesnonfirst</span><span class=“p”>):</span>
<span class=“n”>keeping</span><span class=“p”>[</span><span class=“mf”>0</span><span class=“p”>]</span> <span class=“o”>=</span> <span class=“n”>elem</span>
<span class=“k”>yield</span> <span class=“n”>elem</span>
<span class=“k”>return</span> <span class=“n”>geniter</span>
<span class=“c”># 테스트 부분은 동일</span>
|
네~ 좀 지저분하긴 해 졌는데요;; 실행하면 이렇게~
1
2
3
|
a b c
c d e f a b
b c d e f a
|
모르는 것을 보면 전혀 못 알아볼지라도 찾아보기 좋아하는 어떤 분(^_^)을 위해 용어에 좀 과도하게 링크를 걸었습니다 ^^;