[英]Filter list of tuples for tuples that contain certain items python
我有一個像這樣的元組列表:
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')
也位於列表中,我不希望該元組成為找到了。 我想我沒有指定這個,因為下面所有可行的解決方案也會返回這個元組。
如果我正確理解您的要求,這應該返回預期的結果。 在這里,我們列表轉換為字符串,並使用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
找到 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')]
我不確定是否要指出您要嘗試的內容。 但我會按照以下方式進行操作:
>>>[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')]
你是這個意思嗎
[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)]
此代碼似乎有效,它通過將每個列表划分為與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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.