【问题标题】:Searching for ID from big lists faster in python 2.7?在 python 2.7 中更快地从大列表中搜索 ID?
【发布时间】:2019-05-13 18:55:25
【问题描述】:

所以我有这两个列表:

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

【问题讨论】:

    标签: python list sorting dictionary


    【解决方案1】:

    主要问题是您的数据结构未设置为提供您想要的访问权限。而不是一个字典列表,让它成为你想要使用的自然字典:

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

    现在,您只需制作对应的ids 列表即可

    images_ids = [data[img] for img in image_names]
    

    如果您需要两种访问方法(如果您仍然需要name 和id 标签),那么我建议您学习使用带有name 和id 的Pandas 数据框作为列。这将为您提供两种方法的最佳选择。

    【讨论】:

      【解决方案2】:
      >>> 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']
      

      【讨论】:

        【解决方案3】:

        其他选项:

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

        【讨论】:

        • 最佳答案!好主意!
        【解决方案4】:

        你是对的,它是低效的。您应该使用字典字典或对象字典,而不是使用字典列表:

        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(n),而是在字典中查找 O(1)。

        当然,如果需要,您仍然可以将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)
        

        【讨论】:

          【解决方案5】:

          使用列表理解和过滤器,您可以尝试一下。这适用于您现有的数据,但我强烈建议您根据其他人的建议重新构建您的字典-

          images_ids = [datum.get("id", None) for datum in data for image_name in 
          image_names if datum.get("name", None) == image_name ]
          

          【讨论】:

            【解决方案6】:

            这里不需要 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))
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-04-13
              • 1970-01-01
              • 2015-10-24
              • 1970-01-01
              • 2016-03-19
              • 1970-01-01
              • 2017-12-07
              相关资源
              最近更新 更多