字典列表推导式 - 多个条件

4
我有一个关于列表的多条件问题:

我遇到了一个问题,需要使用多个条件来筛选列表:

listionary = [{u'city': u'paris', u'id': u'1', u'name': u'paul'},
              {u'city': u'madrid', u'id': u'2', u'name': u'paul'},
              {u'city': u'berlin', u'id': u'3', u'name': u'tom'},
              {u'city': u'madrid', u'id': u'4', u'name': u'tom'}]

我试图同时删除符合两个条件的项目。

[elem for elem in listionary if (elem.get('name')!='paul' and elem.get('city')!='madrid')]

在这种情况下,如果满足至少一个条件,则会移除元素,我尝试用几种方式来实现它,有任何想法吗?
期望的输出:
[{u'city': u'paris', u'id': u'1', u'name': u'paul'}
{u'city': u'berlin', u'id': u'3', u'name': u'tom'}
{u'city': u'madrid', u'id': u'4', u'name': u'tom'}]

我想删除满足两个条件的元素。

预期输出是什么? - thefourtheye
4个回答

5
尝试将 and 更改为 or
[elem for elem in listionary if (elem.get('name')!='paul' or elem.get('city')!='madrid')]

记住 德摩根定理。简单来说:当你否定一个布尔表达式时,你需要将 andor 交换,同时将 "==" 和 "!=" 交换。


太好了,这正是我在寻找的。基本逻辑错误,知道了就很好。非常感谢。 - causeyo

5
你的条件应该是这样的:
[e for e in data if not (e.get('name') == 'paul' and e.get('city') == 'madrid')]

输出

[{u'city': u'paris', u'id': u'1', u'name': u'paul'},
 {u'city': u'berlin', u'id': u'3', u'name': u'tom'},
 {u'city': u'madrid', u'id': u'4', u'name': u'tom'}]

这个操作检查当前元素的name是否为paul,并且city是否为madrid。如果两个条件都满足,则外部的not将其反转,结果将为False,该项将被省略。

基本上,您正在检查当前项目是否是不需要的项目,并在是时使if条件失败。


2

您可以使用itemgetter将所有值放入一个元组中,然后进行比较:

>>> from operator import itemgetter
>>> name_and_city = itemgetter('name', 'city')
>>> [e for e in listionary if name_and_city(e) != ('paul', 'madrid')]

1
您的数据实际上是相当静态的。在这种情况下,您可以使用namedtuple来提高大数据的性能。
from collections import namedtuple
Profile = namedtuple('Profile', ['city', 'id', 'name'])
listionary = [Profile(*d) for d in listionary]

为了提高可读性,您可以将条件重构为lambda表达式(假设您使用的是namedtuple):
removed = lambda ele: \
   ele.name == 'paul' or \
   ele.city == 'madrid'
output = [ele for ele in listionary if not removed(ele)]

我认为这种写法更易于维护和阅读,但这取决于谁在查看它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接