我有一个像这样的元组列表:
a = [('1', '2', '5', '5', 'w', 'w', 'w', 'w'),
('1', '3', '5', '5', 'w', 'w', 'w', 'w'),
('1', '3', '4', '5', 'w', 'w', 'w', 'w'),
('1', '4', '4', '4', 'w', 'w', 'w', 'w'),
('1', '5', '5', '5', 'w', 'w', 'w', 'w')]
我希望能够过滤掉包含某些项目的元组。例如,我想专门找到包含'5', '5', 'w', 'w', 'w', 'w'
的所有元组,并将它们放在一个列表中。
filter_for = ['5', '5', 'w', 'w', 'w', 'w']
预期结果将是:
result = [('1', '2', '5', '5', 'w', 'w', 'w', 'w'),
('1', '3', '5', '5', 'w', 'w', 'w', 'w')]
filter_for
的长度变化为1到7,因此我使用and
并不理想。
我尝试过使用
[i for i in a if all(j in filtered_for for j in a)]
但这不起作用。
编辑:如果('1', '5', '5', '5', 'w', 'w', 'w', 'w')
也在列表中,我也不希望找到该元组。我想我没有指定这一点,因为下面的所有工作解决方案也会返回这个元组。
答案 0 :(得分:2)
如果我正确理解您的要求,则应返回预期结果。在这里,我们将列表转换为字符串,并使用in
来检查成员资格。
>>> a = [('1', '2', '5', '5', 'w', 'w', 'w', 'w'),
('1', '3', '5', '5', 'w', 'w', 'w', 'w'),
('1', '3', '4', '5', 'w', 'w', 'w', 'w'),
('1', '4', '4', '4', 'w', 'w', 'w', 'w')]
>>> filter_for = ''.join(['5', '5', 'w', 'w', 'w', 'w'])
>>> print [tup for tup in a if filter_for in ''.join(tup)]
[('1','2','5','5','w','w','w','w'), ('1','3','5','5','w','w','w','w')]
以下代码已更新,以匹配元组列表中的完全子列表。我们采用了一种截然不同的方法,而不是像上面的例子中的模式匹配。
我们首先找到过滤器列表的head
和tail
。然后,我们在head
中找到tail
和tup
出现的位置的索引(我们必须反转 tup
才能找到< / em> tail_index
,因为 index
仅返回匹配的第一个元素。使用我们的索引对,我们可以切换跨越head
和tail
之间距离的子列表。如果此子列表匹配过滤器,则我们知道仅该搜索元组中存在该范围。
def match_list(filter_list, l):
results = []
filter_for = tuple(filter_list)
head = filter_for[0]
tail = filter_for[-1]
for tup in l:
reverse_tup = tup[::-1]
if head and tail in tup:
try:
head_index = tup.index(head)
index_key = reverse_tup.index(tail)
tail_index = -index_key if index_key else None
if tup[head_index:tail_index] == filter_for:
results.append(tup) # Prints out condition-satisfied tuples.
except ValueError:
continue
return results
示例输出
>>> a = [('1', '2', '5', '5', 'w', 'w', 'w', 'w'),
('1', '3', '5', '5', 'w', 'w', 'w', 'w'),
('1', '3', '4', '5', 'w', 'w', 'w', 'w'),
('1', '4', '4', '4', 'w', 'w', 'w', 'w'),
('1', '5', '5', '5', 'w', 'w', 'w', 'w')] # <- Does not match!
>>> filter_for = ['5', '5', 'w', 'w', 'w', 'w']
>>> print match_list(filter_for, a)
[('1','2','5','5','w','w','w','w'), ('1','3','5','5','w','w','w','w')]
答案 1 :(得分:2)
我不确定如果我明白你在想什么。但我会这样做:
>>>[i for i in a if "".join(filter_for) in "".join(i)]
[('1', '2', '5', '5', 'w', 'w', 'w', 'w'), ('1', '3', '5', '5', 'w', 'w', 'w', 'w')]
答案 2 :(得分:0)
你的意思是
[i for i in a if all([j in i for j in filter_for])]
而不是你的线?
[i for i in a if all(j in filter_for for j in a)]
答案 3 :(得分:-1)
此代码似乎有效,它通过将每个列表分成几个与filter_for
相同长度的列表来测试每个列表
修改:我尝试在修改后添加一些排除的模式
a = [('1', '2', '5', '5', 'w', 'w', 'w', 'w'),
('1', '3', '5', '5', 'w', 'w', 'w', 'w'),
('1', '3', '4', '5', 'w', 'w', 'w', 'w'),
('1', '4', '4', '4', 'w', 'w', 'w', 'w'),
('1', '5', '5', '5', 'w', 'w', 'w', 'w')]
filter_for = ['5', '5', 'w', 'w', 'w', 'w']
excluded = [('1', '5', '5', '5', 'w', 'w', 'w', 'w')]
# add a padding key to excluded patterns
for x in range(len(excluded)):
value = excluded[x]
excl = {'value': value}
for i in range(len(value) - len(filter_for) + 1):
if list(value[i:i+len(filter_for)]) == list(filter_for):
excl['padding'] = (i, len(value) - i - len(filter_for))
excluded[x] = excl
def isexcluded(lst, i):
# check if the lst is excluded by one of the `excluded` lists
for excl in excluded:
start_padding, end_padding = excl['padding']
# get start and end indexes
start = max(i-start_padding, 0)
end = min(i + len(excl['value']) + end_padding, len(lst))
if list(lst[start:end]) == list(excl['value']):
return True
return False
def get_lists(lists, length, excluded):
for lst in lists:
# get all the 'sublist', parts of the list that are of the same
# length as filter_for
for i in range(len(lst)-length+1):
tests = [list(lst[i:i+length]) == list(filter_for),
not isexcluded(lst, i)]
if all(tests):
yield lst
result = list(get_lists(a, len(filter_for), excluded))
print(result) # python 2: print result