筛选包含某些项目python的元组的元组列表

时间:2016-08-16 21:01:53

标签: python list tuples

我有一个像这样的元组列表:

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')也在列表中,我也不希望找到该元组。我想我没有指定这一点,因为下面的所有工作解决方案也会返回这个元组。

4 个答案:

答案 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')]

以下代码已更新,以匹配元组列表中的完全子列表。我们采用了一种截然不同的方法,而不是像上面的例子中的模式匹配

我们首先找到过滤器列表的headtail。然后,我们在head中找到tailtup出现的位置的索引(我们必须反转 tup 才能找到< / em> tail_index ,因为 index 仅返回匹配第一个元素。使用我们的索引对,我们可以切换跨越headtail之间距离的子列表。如果此子列表匹配过滤器,则我们知道该搜索元组中存在该范围。

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