2016-07-08 12 views
2

私は4タプルのリストを持っています。 3番目の要素が 'JJ'で、少なくとも1つのタプルが4番目の要素と 'nsubj'が等しい少なくとも1つのタプルがあるかどうかを確認したい。ただし、必ずしも同じタプルである必要はありません。リストの理解のための複数の非結合条件

だから、何かやって -

if (any([tup for tup in parse_tree[i] if (tup[2] == 'JJ' and tup[3] == 'nsubj')])): 

することは間違っています。あなたは

if (any([tup for tup in parse_tree[i] if (tup[2] == 'JJ' or tup[3] == 'nsubj')])): 

を行う場合は、少なくとも1つの条件ではなく、両方を満たすのリストを取得します代わりに

。これを解決するために、私は考えることができ

唯一の方法は、this-

if any([tup for tup in parse_tree[i] if tup[2] == 'JJ']) and any([tup for tup in parse_tree[i] if tup[3] == 'nsubj']): 

1つのリストだけでこれを行う方法はありますかを実行していましたか?

+1

問題は解決しませんが、ジェネレータ式を使用するとランタイムが短縮されます。あなたの最後のステートメントから '[]'を削除する - 'any'は要素が' True'になるとすぐに停止しますが、 '[]'は現在すべての要素を強制的に作成します。 – MisterMiyagi

+1

状態とのリストの理解は悪い考えです。これを行う最も簡単な方法は、あなたが探しているそれぞれの事柄のための簡単なループとフラグです。 – jonrsharpe

+0

@jonrsharpeそんなに気味が悪いですか? –

答えて

1

あなたは可能性があり、その後zipを使用して、別のリストに新しいタプルにグループリスト内のタプルからのすべての3番目と4番目の要素を、これらの新しいタプルから直接要素をチェック:もちろん

# say lst is your original list 

new_lst = zip(*lst) 
if 'JJ' in new_lst[2] and 'nsubj' in new_lst[3]: 
    # your code 

、作成する場合

1

純粋なブール値プラスany/allの解決策は考えられません。プリミティブがなければ、状態を保持するカスタム比較オブジェクトでこれを解決できます。これが適切に両方の条件を評価するよりも遅い 10倍以上であることを

class MultiComp(object): 
    def __init__(self, *conditions): 
     self._conditions = conditions 
     self._results = [False] * len(conditions) 

    def __bool__(self): 
     return all(self._results) 

    __nonzero__ = __bool__ 

    def digest(self, elem): 
     for idx, condition in enumerate(self._conditions): 
      if not self._results[idx] and condition(elem): 
       self._results[idx] = True 
     return self 

comp = MultiComp(lambda tup: tup[2] == 'JJ', lambda tup: tup[3] == 'nsubj') 
any(tup for tup in ttuple if bool(comp.digest(tup))) 

注意。

比較クラス:

In [215]: %%timeit 
    .....: comp = MultiComp(lambda tup: tup[2] == 'JJ', lambda tup: tup[3] == 'nsubj') 
    .....: any(tup for tup in ttuple if bool(comp.digest(tup))) 
    .....: 
10000 loops, best of 3: 30.6 µs per loop 

が正しくジェネレータを使用して:

In [216]: %%timeit 
    .....: any(tup[2] == 'JJ' for tup in ttuple) and any(tup[3] == 'nsubj' for tup in ttuple) 
    .....: 
100000 loops, best of 3: 4.26 µs per loop 
0

をたぶんあなたは(より効率的です)発電機の代わりに、リスト自体を使用してのような何かを行うことができます。

1つのリストでのみ実行する必要がある具体的な理由はありますか?

if any(True for tuple_list in list_of_tuple_lists if any(True for t in tuple_list if t[2]=='JJ') and any(True for t in tuple_list if t[3] == 'nsubj')) 

そして、あなたの命名と一致する:

if any(True for tuple_list in parse_tree[i] if any(True for t in tuple_list if t[2]=='JJ') and any(True for t in tuple_list if t[3] == 'nsubj')) 

コードは、すべてのケースのために働くことを。簡単なテスト:

import random 
import time 

none = [(1,2,3,4),(1,2,3,4),(1,2,3,4),(1,2,3,4)] # none of the conditions 
first = [(1,2,3,4),(1,2,'JJ',4),(1,2,3,4),(1,2,3,4)]# only first of the conditions 
second = [(1,2,3,4),(1,2,'test',4),(1,2,4,'nsubj'),(1,2,3,4)]# only second of the conditions 
both = [(1,2,'JJ',4),(1,2,'test',4),(1,2,3,'nsubj'),(1,2,3,4)]# both of the conditions in different tuples 
same = [(1,2,'JJ','nsubj'),(1,2,'test',4),(1,2,2,4),(1,2,3,4)]# both of the conditions in same tuple 
possible_tuples=[none,first,second,both,same] 


def our_check(list_of_tuple_lists): 
    if any(True for tuple_list in list_of_tuple_lists if any(True for t in tuple_list if t[2]=='JJ') and any(True for t in tuple_list if t[3] == 'nsubj')): 
     return True 
    else: 
     return False 


def our_check_w_lists(list_of_tuple_lists): 
    if any([True for tuple_list in list_of_tuple_lists 
      if any([True for t in tuple_list if t[2]=='JJ']) and any([True for t in tuple_list if t[3] == 'nsubj'])]): 
     return True 
    else: 
     return False 


def third_snippet(list_of_tuple_lists): 
    if any([tup for tup in list_of_tuple_lists if tup[2] == 'JJ']) and any([tup for tup in list_of_tuple_lists if tup[3] == 'nsubj']): 
     return True 
    else: 
     return False 

def test(func): 
    test_cases = [] 
    for n in range(100000): 
     test_list=[] 
     for i in range(10): 
      test_list.append(random.choice(possible_tuples)) 
     expected = False 
     if both in test_list or same in test_list: 
      expected = True 

     test_case = expected, test_list 
     test_cases.append(test_case) 
    start = time.clock() 
    for expected, case_list in test_cases: 
     if expected != func(case_list): 
      print('%s, Fail for: %s'%(func,case_list)) 
      return False 
    end = time.clock() 
    print('function:%s, %f'%(func, end-start)) 

test(our_check) 
test(our_check_w_lists) 
test(third_snippet) 

このテスト結果は、ちょうどわずか10組の長いリストについては、発電機やリストの内包表記を使用して間の実行時間の違いを示しています。

function:<function our_check at 0x00000000028CE7B8>, 0.378369 
function:<function our_check_w_lists at 0x00000000031472F0>, 1.270924 
<function third_snippet at 0x00000000031E0840>, Fail for: [[... 
+0

答えに感謝しますが、基本的には私がやっていることを正確にやっているのではなく、それを関数に入れていますか? –

+0

@NikhilPrabhu私はテストのための関数を入れました。上記の短いスニペットを使用して、list_of_tuple_listsがあなたのコードと一致するようにparse_tree [i]にすることができます。それはジェネレータのみを使用し、リストを作成していないので、同じことをしていません。引数としてgeneratorを指定したAny()文は、Trueになると停止します。 []リストの理解を使用すると、条件が満たされる場所と条件に関係なく、完全なリストが生成されます。あなたの3番目のスニペットが私のテストで失敗するのに加えて。 –

+0

@NikhilPrabhu私は、ジェネレータとリストの理解を使用する間のパフォーマンスの違いを示すために私の答えを更新しました。 –

関連する問題