【问题标题】:Filter list of tuples for tuples that contain certain items python过滤包含某些项目的元组的元组列表python
【发布时间】:2016-12-23 09:22:25
【问题描述】:

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

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

【问题讨论】:

  • 1. “似乎不起作用” 究竟是什么意思? 2.如果你想匹配那些元素的正确位置,为什么不zip呢?
  • a 的所有元素和filter_for 的所有元素是否总是1个字符的字符串?
  • 您的编辑使这个问题过于主观。你是说如果序列的头部或尾部有array[head - 1] == array[head]array[tail] == array[tail + 1] 过滤器应该失败?
  • @Robᵩ 是的,a 的所有元素和 filter_for 的所有元素始终是 1 个字符串
  • 嗯,很快就会更新我的答案。

标签: python list tuples


【解决方案1】:

如果我正确理解您的要求,这应该会返回预期的结果。这里我们将列表转换为字符串,并使用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。然后我们在tup 中找到headtail 出现的索引(我们必须反转 tup 找到 tail_index, as 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')]  

【讨论】:

  • @hopla,我已进行更改以处理您的最新编辑。
【解决方案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')]

【讨论】:

  • 如果所有元素都是 1 个字符的字符串,则此方法可以正常工作。在其他情况下它可能不起作用。
  • 对不起,我不明白你的意思。你能给我解释一下吗?它适用于 a = [('11', '22', '5', '5', 'w', 'w', 'w', 'w')] 那你是什么意思?谢谢
  • 1) 这一点没有实际意义。 OP 已澄清所有输入均为 1 个字符的字符串。 2)考虑a = [['12', '34']]; filter_for = ['2', '3']。您的解决方案会找到匹配项,即使它不存在。 3)考虑a = [['1', 4.75]]; filter_for = ['1']。您的解决方案将引发异常。
【解决方案3】:

你是不是这个意思

[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)]

【讨论】:

  • 两者都应该工作 all(j in filter_for for j in a) 迭代生成器 (j in filter_for for j in a)。当生成器表达式是函数的唯一参数时,您不需要在生成器表达式周围添加括号。
【解决方案4】:

这段代码似乎有效,它通过将每个列表划分为与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

【讨论】:

    猜你喜欢
    • 2020-12-25
    • 2017-05-24
    • 2022-06-14
    • 2016-09-25
    • 1970-01-01
    • 2020-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多