2012-04-20 16 views
2

私はこの問題をはっきり説明することができれば幸いです。私はPythonの実験者(念のため、以下のクエリはナイーブ表示されます)Pythonデータセットで単語パターンを検索する

よ、私は、フォームのデータセットを持っていると仮定します。

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に上がります。

誰も私がこのような種類の操作をPythonで行うことができますか?私は基数を調べましたが、私はそれが私を助けるとは思わない。

おかげで、 サーガル

+1

最後のタプルに4つの数字があったのでしょうか? –

+0

はい。これは私の例のように> 1、3、4のいずれの数字でもかまいません。 – Learnerbeaver

答えて

2

あなたがこれを行うにはcollections.Counterを使用することができます。私も、前のPython 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}) 

ました不確実な長さのタプルがある場合にのみ必要です。 Pythonの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様な構文を持っているあなたは、彼らができなくなり、この場合には、問題が発生した可能性があり、彼らは、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]は私にとっては可変です。つまり、まずCounter(item [0]、item [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遅くなります。 defaultdictは少し速く同じようなことを達成することができます

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

あなたはCS-スタイル効率的な方法でこれを実行したい場合は、triesをご覧ください。ルートに各サブツリーのサイズを格納するには、わずかな変更が必要ですが、それはあまり難しくありません。

+0

私は効率的な観点からトライを試みました。実際、根木が最高でした。しかし、私はpytrieとpyradixパッケージのPython実装を使用することについて多くのGoogleの助けを得ることができませんでした。だから、私は失敗しました。彼らがどのように動作するのか分かっていれば、彼らは最適なソリューションだと私は同意します。 – Learnerbeaver

+0

+1、これは最適なパフォーマンスが必要な場合には良い解決策ですが、より多くの実装が必要になるため、単純な "Counter"アプローチが高速* *であれば、それは重要です。 –

関連する問題