Python:从迭代器内的列表中删除元素?

时间:2015-02-01 21:41:56

标签: python

我正在尝试从Python中的列表中删除元素。大多数答案似乎都表明使用列表迭代器是最好的,但我不认为它对我的问题是可能的(或者至少是优雅的)。

我想迭代test_data列表并删除满足以下两个条件的所有项:(1)具有属性total:sum(2)具有属性(pagePath)以mystrings列表中的任何元素开头但不等于。

这是我的字符串列表,以及我的测试数据:

    mystrings = [u'/calculate-state-pension', u'/check-uk-visa']
    test_data = [
        {
            "pagePath": "/check-uk-visa",
            "total:sum": 2.0
        },
        {
            "pagePath": "/check-uk-visa/y",
            "total:sum": 3.0
        },
        {
            "pagePath": "/check-uk-visa/n",
            "total:sum": 4.0
        },
        {
            "pagePath": "/bank-holidays",
            "total:sum": 2.0
        },
        {
            "pagePath": "/check-uk-visa",
            "searchUniques:sum": 2.0
        }
    ]

所以我想最终得到这个清单:

    results = [
        {
            "pagePath": "/check-uk-visa",
            "total:sum": 2.0
        },
        {
            "pagePath": "/bank-holidays",
            "total:sum": 2.0
        },
        {
            "pagePath": "/check-uk-visa",
            "searchUniques:sum": 2.0
        }
    ]

这是我的代码:

    results = test_data[:]
    for r in results_copy:
        for s in mystrings:
            if 'total:sum' in r and r['pagePath'].startswith(s) \
                 and r['pagePath'] != s:
                results.remove(r)
    return results

但这似乎不起作用。它会删除/check-uk-visa/y但不包含/check-uk-visa/n的元素。

我做错了什么?我认为它与删除和迭代器有关 - 它看起来像是在跳过元素。

2 个答案:

答案 0 :(得分:2)

您想要any组合,其中"pagePath"值以字符串列表中的字符串开头,但不等于字符串。

for dic in test_data[:]:
    s = dic.get("pagePath","")
    if "total:sum" in dic and any(s.startswith(y) and s != y  for y in mystrings):
        test_data.remove(dic)

[{'total:sum': 2.0, 'pagePath': '/check-uk-visa'}, {'total:sum': 2.0, 'pagePath': '/bank-holidays'}, {'searchUniques:sum': 2.0, 'pagePath': '/check-uk-visa'}]

有一点需要注意的是,如果你的mystrings列表中有类似的字符串,其中一个字符串可能以相同的字母开头但不等于但可能等于另一个字符串,所以在这种情况下我们可以使用一组来进行0(1)次查找和使用英寸

mystrings = {u'/calculate-state-pension', u'/check-uk-visa'}

for dic in test_data[:]:
    s = dic.get("pagePath","")
    if "total:sum" in dic and any(s.startswith(y) for y in mystrings)and s not in mystrings:
        test_data.remove(dic)
print(test_data)

答案 1 :(得分:1)

过滤此类内容的最简单方法通常是使用filter函数。

results_copy = filter(lambda r: ('total:sum' in r
                                 and any([r['pagePath'].startswith(s) 
                                                             for s in mystrings])
                                 and r['pagePath'] not in mystrings), 
                      results)

或者,您可以使用列表推导。除了过滤之外,有时想要进行一些处理时更容易阅读:

results_copy = [r for r in results if ('total:sum' in r
                                       and any([r['pagePath'].startswith(s) 
                                                             for s in mystrings])
                                       and r['pagePath'] not in mystrings)]