【问题标题】:Fastest way to compare a list to a dict of lists将列表与列表字典进行比较的最快方法
【发布时间】:2019-09-03 16:48:22
【问题描述】:

所以我有 2 个列表:

list1 = ['abc', 'efg', 'hijk'] #list of strings

list2 = ['lmno', 'pqrs'] #also a list of strings

然后我有一个相当大的字典 通常,列表中只有大约 100 个键和几十万个字符串值

d = {'abc': ['lmno'], 'efg': ['lmno', 'pqrs']}

所以我需要遍历list1的每一项和list2的每一项:

示例:

for i1 in list1:
   for i2 in list2:
      print(i1, i2)

然后将数据与字典进行比较:

for i1 in list1:
   for i2 in list2:
      if i1.lower() in d:
         if i2 in d[i1.lower()]:
             continue #ignore
         else:
             #process data

目前,我的代码和上面一样,但是当字典很大时它很慢 有更快的方法吗?

for i1 in list1:
   for i2 in list2:
      if i1.lower() in d:
         if i2 in d[i1.lower()]:
             continue #ignore
         else:
             #process data

【问题讨论】:

  • 使用集合的字典而不是列表的字典。
  • #process data 你也需要钥匙吗?还是只有价值观?
  • 如果 list1 中的至少一个字符串是您的 dict 中的键,您想处理数据吗?并且列表 2 中的至少一个字符串应该在 dict[key_lsit1] 中?因为目前你正在做process data 这么多次,因为 list2 中的元素在 dict[key_lsit1] 中,似乎效率低下

标签: python python-3.x list dictionary


【解决方案1】:

交换第二行和第三行,这样如果i1.lower() 不在d 中,您就不会遍历list2

for i1 in list1:
    if i1.lower() in d:
        for i2 in list2:
            if i2 in d[i1.lower()]:
                continue #ignore
            else:
                 #process data

另外,正如@aran-fey 提到的,首先将您的d 转换为集合的字典:

d = {k: set(v) for k, v in d.items()}

更进一步(感谢@AlexHall):

d = {k: set(v) for k, v in d.items()}
set2 = {i2.lower() for i2 in list2}

for i1 in list1:
    for i2 in set2 - d.get(i1.lower(), set()):
         #process data

【讨论】:

  • 也将列表转换为集合,然后你可以写for i2 in d.get(i1.lower(), set()) - set2: process(i1, i2)
【解决方案2】:

也许不是最快的,您必须检查一下。但它更整洁。

from operator import itemgetter

keys_to_check = [
    'abc', 'efg', 'hijk'
]

strings_to_check = [
    'lmno', 'pqrs'
]

d = {
    'abc': ['lmno'],
    'efg': ['lmno', 'pqrs']
}

# Makes function that will get values for specified keys
# . Checks if the key is within dictionary
values = itemgetter(*(key.lower() for key in keys_to_check if key.lower() in d))

for value in values(d):
    # Checks if any fo strings within value is in the strings_to_check
    # . if so, ignore that value
    if any(strng in strings_to_check for strng in value):
        continue
    else:
        # process data

【讨论】:

    【解决方案3】:

    我猜你有两个列表,一个包含键,另一个包含值。 您需要在迭代值之前检查 dict 中的键,这将提高效率。

    for i1 in list1:
      if i1.lower() in d:
        for i2 in list2:
                if i2 in d[i1.lower()]:
                    continue #ignore
                else:
                    #process data
    

    【讨论】:

    • 我们在 12 分钟前得到了相同的答案。
    猜你喜欢
    • 1970-01-01
    • 2017-06-21
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多