Python 列表理解的多个非连接条件
我有一个4元组的列表。我想检查是否至少有一个元组的第三个元素等于'JJ',并且至少有一个元组的第四个元素等于'nsubj'。但是,它们不一定是同一个元组 所以做一些类似于-Python 列表理解的多个非连接条件,python,list,Python,List,我有一个4元组的列表。我想检查是否至少有一个元组的第三个元素等于'JJ',并且至少有一个元组的第四个元素等于'nsubj'。但是,它们不一定是同一个元组 所以做一些类似于- 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 t
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')])):
您将得到至少满足一个条件但不能同时满足两个条件的列表
我认为解决这个问题的唯一办法就是这样做-
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']):
只有一个列表有办法做到这一点吗?您可以使用
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
当然,如果允许从原始列表创建新列表我想不出一个纯粹的布尔加
任何/所有
解决方案。如果没有原语,您可以使用保持状态的自定义比较对象来解决此问题
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
也许你可以做一些事情,比如使用生成器(效率更高),而不是列表本身 是否有任何特定的原因,你需要它只做一个列表
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.378369
功能:,1.270924
,失败原因:[[…]。。。
虽然它不能解决您的问题,但使用生成器表达式将减少其运行时间。从上一条语句中删除[]
-任何都将在元素为True
时停止,但[]
此时强制创建所有元素。使用状态为的列表理解是一个坏主意。最简单的方法是直接循环,并为您要查找的每件事情标记标记。@jonrsharpe不是那么不和谐吗?只不过是尝试将其塞进一行无法读取的内容中而已!谢谢您的回答,但这基本上不是d吗我正在做什么,但把它放在函数中?@nikhiprabhu我刚刚放在函数中进行测试。你可以使用上面的简短片段,其中的列表将是parse_tree[I],以匹配你的代码。它没有做同样的事,因为它只使用生成器,没有创建任何列表。any()以generator作为参数的语句将在其变为真时停止。使用[]列表理解将导致生成完整的列表,无论何时何地满足条件。此外,您的第三个片段在我的测试中失败。@Nikhiprabhu我更新了我的答案,以显示使用生成器和列表理解在性能上的差异。哇,这是一个很大的差异。我必须承认,我没有注意到您在您的答案中,从any()函数中删除了list对象。但是,我的主要问题是,作为一个条件,在一行中写入我想要的内容。无论如何,谢谢!@nikhiprabhu!它在一行中作为单个if:if any(对于tuple\u列表中的tuple\u list,如果有,则为True)(对于tuple\u列表中的t,如果t[2]='JJ')和any(对于tuple\u列表中的t,则为True,如果t[3]=='nsubj'))我刚刚将其格式化为在站点上更可读的代码片段,并移动到函数以测试性能。您只需将其内联到语句中即可。