根据第二个列表过滤列表

时间:2012-08-09 21:38:27

标签: python

这可能是一个简单的问题,但我无法自己找到一个直截了当的答案。

给出两个列表,一个只有一个id列表,另一个列出所有数据,包括一些我们不关心的id:
all_data = [['abc', 123], ['cde', 234], ['fgh', 345]]
ids = ['abc', 'fgh']

获取以下输出的最佳方法是什么,请注意它只保留具有相同ID的那些: new_data = [['abc', 123], ['fgh', 345]]

我当前的代码类似于:

for x in all_data:
    for y in ids:
         if x[0] == y:
              new_data.append(x)

你有什么不同的做法?是否有内置功能可以解决这个我错过的地方?

(我说“类似的东西”,因为它实际上是一个非常长的序列,涉及集合,所有这就是为什么没有“pythonic”单行分享。)

更新: 嗯,你们很有趣。

我怎么做得更难一点。如果不是“all_data”我有一个字典all_data_dict,它有几个与“all_data”格式相同的列表条目怎么办?按照规则,我会确保接受原始问题的答案,但是如果你们都希望跟上这些乐趣,那么让我们看看我们得到了什么!

5 个答案:

答案 0 :(得分:7)

使用列表推导,其中条件检查集合中的成员资格:

>>> all_data = [['abc', 123], ['cde', 234], ['fgh', 345]]
>>> ids = ['abc', 'fgh']
>>> id_set = set(ids)
>>> [s for s in all_data if s[0] in id_set]
[['abc', 123], ['fgh', 345]]

答案 1 :(得分:7)

在评论后编辑,我打算使用一套。 正如雷蒙德在他的回答中建议使用列表理解:)和一组ids。

all_data = [['abc', 123], ['cde', 234], ['fgh', 345]]
ids = set(['abc', 'fgh'])
filtered_data = [x for x in all_data if x[0] in ids]

答案 2 :(得分:2)

您应该将all_data变成字典,因为您可以像使用它一样:

d = dict(all_data)
new_data = [(k, d[k]) for k in ids]

这将使用ids给出的顺序,而不是all_data给出的顺序。

答案 3 :(得分:2)

因为许多人使用过dicts或LC,我认为我应该展示filter

>>> all_data = [['abc', 123], ['cde', 234], ['fgh', 345]]    
>>> ids = set(['abc', 'fgh'])
>>> values = filter(lambda value: value[0] in ids, all_data)
>>> values
[['abc', 123], ['fgh', 345]]
>>> 

第二部分。

>>> all_data_dict = {'abc':all_data, 'cde':all_data, 'fgh':all_data}
>>> ids = set(['abc', 'fgh'])
>>> dict(filter(lambda value: value[0] in ids, all_data_dict.items()))
{'abc': [['abc', 123], ['cde', 234], ['fgh', 345]], 'fgh': [['abc', 123], ['cde', 234], ['fgh', 345]]}

答案 4 :(得分:0)

你的第二个问题并不困难,只是从一开始就构建数据的正确方法:

>>> all_data = {'abc': 123, 'cde': 234,'fgh': 345}  # a dict
>>> ids = {'abc', 'fgh'}  # a set
>>> {k:v for k,v in all_data.viewitems() if k in ids}
{'abc': 123, 'fgh': 345}

顺便说一下,获得匹配键的一个很好的快速方法是:

>>> all_data.viewkeys() & ids 
set(['abc', 'fgh'])