2012-04-20 3 views
2

이 문제를 명확하게 설명 할 수 있기를 바랍니다. 파이썬 데이터 집합에서 단어 패턴 검색

a = (('309','308','308'), ('309','308','307'), ('308', '309','306', '304')) 

날 경로 각 ('309','308','308')을 부르 자 : 나는 파이썬 실험 해요

내가 형태의 데이터 집합을 가지고 있다고 가정 (단지의 경우 아래의 쿼리는 순진 나타납니다).

다음의 수를 찾고 싶습니다.

a. Count('309','308', <any word>)

b. Count('309',<any word>,'308')

및 모든 가능한 순열.

나는이 검색을 달성하는 데 도움이되는 일종의 정규식을 생각하고 있습니다. 그리고, 내가 가지고있는 경로의 수가 50000으로 넘어갑니다.

누구나 내가 이런 종류의 작업을 어떻게 할 수 있는지 제안 할 수 있습니까? 나는 기아를 탐험했다. 그러나 나는 그것이 나를 도와 줄 것이다라고 생각하지 않는다.

감사합니다, 사가르

+1

마지막 튜플에 네 개의 숫자가 있어야하나요? –

+0

예 .. 내 예와 같이 3보다 많거나 1이 아닌 숫자가 될 수 있습니다. – Learnerbeaver

답변

2

당신은이 작업을 수행 할 collections.Counter을 사용할 수 있습니다 나는 또한, 사전 파이썬 3.x에 존재하지 않았다, 여기 풀고 확장 된 튜플을 사용하고

>>> from collections import Counter 
>>> a = (('309','308','308'), ('309','308','307'), ('308', '309','306', '304')) 
>>> Counter((x, y) for (x, y, *z) in a) 
Counter({('309', '308'): 2, ('308', '309'): 1}) 
>>> Counter((x, z) for (x, y, z, *w) in a) 
Counter({('308', '306'): 1, ('309', '308'): 1, ('309', '307'): 1}) 

하는 불확실한 길이의 튜플이있는 경우에만 필요합니다. 파이썬 2.x에서는 다음과 같이 할 수 있습니다.

Counter((item[0], item[1]) for item in a) 

그러나 이것이 얼마나 효율적인지는 말할 수 없습니다. 나는 그것이 나쁘다는 것을 믿지 않는다.

>>> count = Counter((x, y) for (x, y, *z) in a) 
>>> count['309', '308'] 
2 

편집 :

Counterdict -like 문법을 가지고 당신은 그들이 할 수 없습니다이 경우에, 당신은 문제가 실행할 수 그들이, 1보다 큰 길이의 수 있습니다 언급 요구되는 길이보다 짧으면 포장을 푸십시오.

Counter((item[0], item[1]) for item in a if len(item) >= 2) 

예 :이 솔루션은 필요한 형식으로 어떤하지를 무시하는 발전기 표현을 변경하는 것입니다

>>> a = (('309',), ('309','308','308'), ('309','308','307'), ('308', '309','306', '304')) 
>>> Counter((x, y) for (x, y, *z) in a) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python3.2/collections.py", line 460, in __init__ 
    self.update(iterable, **kwds) 
    File "/usr/lib/python3.2/collections.py", line 540, in update 
    _count_elements(self, iterable) 
    File "<stdin>", line 1, in <genexpr> 
ValueError: need more than 1 value to unpack 
>>> Counter((item[0], item[1]) for item in a) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python3.2/collections.py", line 460, in __init__ 
    self.update(iterable, **kwds) 
    File "/usr/lib/python3.2/collections.py", line 540, in update 
    _count_elements(self, iterable) 
    File "<stdin>", line 1, in <genexpr> 
IndexError: tuple index out of range 
>>> Counter((item[0], item[1]) for item in a if len(item) >= 2) 
Counter({('309', '308'): 2, ('308', '309'): 1}) 

는 가변 길이의 수를 가지고해야하는 경우, 가장 쉬운 방법은을 사용하는 것입니다 목록 슬라이스 :

:

물론
start = 0 
end = 2 
Counter(item[start:end] for item in a if len(item) >= start+end) 

, 이것은 단지 개별적으로 열을 선택하려는 경우, 당신은 좀 더 작업을해야 지속적인 실행 작동

def pick(seq, indices): 
    return tuple([seq[i] for i in indices]) 

columns = [1, 3] 
maximum = max(columns) 
Counter(pick(item, columns) for item in a if len(item) > maximum) 
+0

확인. 이 개념은 재미있어 보인다. 결코 그것을 알지 못했다. 그래서, 나는 50000 개의 경로를 가진 파일에서 a를 읽을 것이다. 그리고 나서 카운터 개념을 루프로 사용하여 결정합니다. 내가 어떻게 작동하게 할 수 있는지 알아 보자. 그러나 당신의 도움은 대단합니다. 엄청 고마워! – Learnerbeaver

+0

Sagar : 잠재적으로 짧은 튜플에 대한 요지를 적어 두었습니다. 이 질문에 대한 답변이 있으면 [답변을 수락 해주십시오] (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235). –

+0

새로운 문제가 있습니다. 항목 [0], 항목 [1]은 (는) 가변적입니다. 즉, 먼저 카운터 (항목 [0], 항목 [1])를 계산해야합니다. 나는 프로그래밍 할 때 아이템 [i]의 숫자를 모른다. 이견있는 사람? – Learnerbeaver

0

pre-Python 2 인 경우.7, 당신은 지능형리스트를 사용할 수 있습니다

#Number of: ('309','308', <any word>) 
>>> len([i[0] for i in a if i[0]=='309' and i[1]=='308']) 
2 
#Number of:('309',<any word>,'308') 
>>> len([i[0] for i in a if i[0]=='309' and i[-1]=='308']) 
1 

목록 comrehension를 사용하는 것은 다소 빠른 Counter를 사용하는 것보다 것 같다, 그리고 튜플 풀기 좋은 있지만, 그것은 또한 물건을 조금 downa 느려집니다. 당신은 CS-스타일 효율적인 방법으로이 작업을 수행하려면 당신은 tries 보라,

from collections import Counter, defaultdict 

a = [] 
for i in range(500000): 
    a.append(('309','308','308')) 

def ww(a): 
    return Counter((item[0], item[1]) for item in a) 

def xx(a): 
    return len([i[0] for i in a if i[0]=='309' and i[1]=='308']) 

def yy(a): 
    g = defaultdict(int) 
    for i in a: 
     g[(i[0],i[1])] += 1 
    return g 

def zz(a): 
    return Counter((i, j) for (i, j, *k) in a) 

from timeit import timeit 
print('Counter..:',timeit("ww(a)", "from __main__ import ww, a", number=100)) 
print('compreh..:',timeit("xx(a)", "from __main__ import xx, a", number=100)) 
print('defdict..:',timeit("yy(a)", "from __main__ import yy, a", number=100)) 
print('Count+un.:',timeit("zz(a)", "from __main__ import zz, a", number=100)) 
#output: 
Counter..: 8.411258935928345 
compreh..: 2.8653810024261475 
defdict..: 4.256785154342651 
Count+un.: 18.45333218574524 
2

: defaultdict 조금 더 빨리 비슷한 일 수행 할 수 있습니다. 루트에 각 하위 트리의 크기를 저장하려면 약간의 수정이 필요하지만 너무 어렵지는 않습니다.

+0

나는 효율의 관점에서 trie를 시도했다. 사실, 기수 나무가 최고 였을 것입니다. 하지만 python과 pyradix 패키지의 python 구현을 사용하는 데 많은 도움을 얻을 수 없었습니다. 그래서 나는 실패했다. 그들이 어떻게 일할 것인지를 안다면, 나는 그들이 최적의 해결책이라고 동의한다. – Learnerbeaver

+0

+1, 최적의 성능이 필요한 경우 좋은 해결책입니다. 그러나 구현이 훨씬 더 필요하므로 간단한 "카운터"접근 방식이 빠르면 충분합니다. –