在Python 2.7中如何更快地从大型列表中搜索ID?

4

我有两个列表:

image_names = ["IMG_1.jpg", "IMG_2.jpg"]
data = [{"name": "IMG_1.jpg", "id": "53567"},
        {"name": "IMG_2.jpg", "id": "53568"},
        {"name": "IMG_3.jpg", "id": "53569"},
        {"name": "IMG_4.jpg", "id": "53570"}]

我希望能够在data的images_names中搜索第一项,然后搜索下一项,以此类推。如果名称相同,则获取其ID并将其添加到列表中。
这是我的实现方式:
for image_name in image_names:
    for datum in data:
        datum_name = datum.get("name", None)
        if datum_name == image_name:
           images_ids.append(datum.get("id", None))

目前它的效果很好,但是一旦我在images_names和data中有大量数据,我认为这样做非常低效。在Python中,最好的方法是什么?我正在使用python 2.7

6个回答

4
主要问题在于你的数据结构无法提供你想要的访问方式。不要用字典列表,而是使用自然的字典结构来解决这个问题:
data = {"IMG_1.jpg": "53567",
        "IMG_2.jpg": "53568",
        "IMG_3.jpg": "53569",
        "IMG_4.jpg": "53570"}

现在,你只需要制作相应的id列表即可。
images_ids = [data[img] for img in image_names]

如果您需要同时使用这两种访问方法(如果您仍然需要nameid标签),那么我建议您学习使用Pandas数据框,将nameid作为列。这样可以兼顾两种方法的优点。

3
>>> images_ids = [filter(lambda x: x['name'] == name, data) for name in image_names]
>>> images_ids = [i[0]['id'] for i in images_ids if i]
>>> images_ids
['53567', '53568']

2

其他选项:

[ item["id"] for item in data if item["name"] in image_names]
#=> ['53567', '53568']

如果存在具有相同名称但不同id的图像,则它也适用:

data = [{"name": "IMG_1.jpg", "id": "53500"},{"name": "IMG_1.jpg", "id": "53501"}]
#=> ['53500', '53501']

最佳答案!很棒的思考! - Abhisek Roy

1

您说得对,这种方法效率低下。您应该使用字典的字典或对象的字典,而不是使用字典列表:

data = {"IMG_1.jpg": {"id": "53567"},
    "IMG_2.jpg": {"id": "53568"},
    "IMG_3.jpg": {"id": "53569"},
    "IMG_4.jpg": {"id": "53570"}}

for image_name in image_names:
    if (image_name in data):
        image_ids.append(data[image_name]["id"])

使用字典进行查找的时间复杂度为O(1),而使用列表则为O(n)。

当然,如果您愿意,仍然可以将name作为子字典的键,我只是为了简化而删除了它。但真正的终极目标是建立一个类:

class ImageData:

    def __init__(self, name, id):
        self.Name = name
        self.Id = id

data = {"IMG_1.jpg": ImageData("IMG_1.jpg", "53567"),
    "IMG_2.jpg": ImageData("IMG_2.jpg", "53568"),
    "IMG_3.jpg": ImageData("IMG_3.jpg", "53569"),
    "IMG_4.jpg": ImageData("IMG_4.jpg", "53570")}

for image_name in image_names:
    if (image_name in data):
        image_ids.append(data[image_name].Id)

0
使用列表推导和过滤器,您可以尝试这个。这适用于您现有的数据,但我强烈建议您按照其他人的建议重新构造字典。
images_ids = [datum.get("id", None) for datum in data for image_name in 
image_names if datum.get("name", None) == image_name ]

0

这里不需要2个循环。您可以迭代第一个循环并在第二个列表中搜索图像名称,如果匹配,则将ID添加到图像ID中。如下所示

    for datum in data:
          datum_name = datum.get("name", None)
          if any(datum_name in s for s in image_names):
                 images_ids.append(datum.get("id", None))

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