【问题标题】:handling 900 000 items in a list "quickly" when needed to access it multiple times?需要多次访问时“快速”处理列表中的 900 000 个项目?
【发布时间】:2021-08-25 02:06:21
【问题描述】:

我有一个用例,我将“链接”拉入服务器文件共享上的文件。

然后我需要对这些链接运行一些正则表达式检查并将它们分解成特定的部分,以便我可以对它们进行排序。

排序后,我需要在 x 个服务器之间拆分列表以开始拉取它们。排序很重要,因为每个拆分都需要均匀。

 ['/local/custom_name/a_database/database_name_56_1118843/file_1.tgz']
 ['/local/custom_name/a_database/database_name_56_1118843/file_3.tgz']
 ['/local/custom_name/a_database/database_name_56_1118843/file_4.tgz']
 ['/local/custom_name/a_database/database_name_56_1118843/file_2.tgz']

 ['/local/custom_name/a_database/database_name_655_1118843/file_1.tgz']
 ['/local/custom_name/a_database/database_name_655_1118843/file_2.tgz']
 ['/local/custom_name/a_database/database_name_655_1118843/file_3.tgz']
 ['/local/custom_name/a_database/database_name_655_1118843/file_4.tgz']
 
 ['/local/custom_name_4/b_database/database_name_5242_11132428843/file_1.tgz']
 ['/local/custom_name_4/b_database/database_name_5242_11132428843/file_2.tgz']

 ['/shared/custom_name/c_database/database_name_56_1118843/file_1.tgz']
 ['/shared/custom_name/c_database/database_name_56_1118843/file_2.tgz']
 
 ['/local/custom_name_4/c_database/database_name_58_1118843/file_1.tgz']
 ['/local/custom_name/ac_database/database_name_58_1118843/file_2.tgz']

例如,由于 a_database 中有 8 个文件,每个名称有 4 个文件,那么说 4 个服务器,我需要每个路径中的一个文件才能访问每个服务器。

我所做的是查看每个链接,然后将路径分解为字典,其中第一个值是唯一的 id:

{'uid' : 'local_custom_name_a_database_database_name_56', 'link_list': [] }

然后在我再次浏览原始列表并添加任何适合该字典的链接后:

{'uid' : 'local_custom_name_a_database_database_name_56', 'link_list': [ 
'/local/custom_name/a_database/database_name_56_1118843/file_1.tgz', 
'/local/custom_name/a_database/database_name_56_1118843/file_3.tgz', 
'/local/custom_name/a_database/database_name_56_1118843/file_4.tgz',
'/local/custom_name/a_database/database_name_56_1118843/file_2.tgz'
]}

然后在服务器之间拆分链接列表。

所有这些都按预期工作,但是第二部分,我将原始链接与新字典 uid 进行比较并将链接添加到列表中需要很长时间。对于 10 000 个项目,它需要几分钟,但对于 900 000 个项目,它看起来需要大约 125 小时。这是不行的。

实际数据更复杂,并且正在进行大量排序,但这不是瓶颈。瓶颈在哪里描述。虽然逻辑有效,但我确信我没有以最有效的方式这样做。

感谢任何帮助。甚至只是向我指出一种更好的方法来处理原生列表和列表或字典列表之外的这么多项目。

【问题讨论】:

  • 您可以尝试在 1 步中完成这两个步骤,方法是在 O(n) 时间内迭代原始列表。遍历原始列表,提取uid,检查字典中是否存在uid,如果存在则更新链接列表中的字典,否则添加键并将链接列表初始化为空。
  • 我想到了这一点,也许我错了,但是我得到了正在处理的项目的 UID,并且我将该 uid 的 dict 添加到具有空链接列表的列表中,如您所提到的。然后在最后消除重复。然后再次遍历并将每个添加到列表中。 tmp_dict_list.append(uid_dict_with_empty_list)。如果我必须在 tmp_dict_list 中为 d 再做一次,只是为了查看 uid 是否已经存在。这不是很慢吗?因为 tmp_dict_list 到最后会很大,每个人都必须迭代它以查看它是否存在。我觉得我已经在做什么了?我想尝试它没有坏处

标签: python python-3.x list optimization large-data


【解决方案1】:

如果性能是一个问题,这种类型的数据结构{'uid' : 'local_custom_name_a_database_database_name_56', 'link_list': [] } 将是一个问题。根据 UID 查找元素是 O(n)。相反,您需要一个将 UID 直接映射到链接列表的字典。这允许 O(1) 访问。如果需要,您可以稍后转换数据。

我不知道获取 UID 背后的确切逻辑,所以我只举一个例子:

l = [
    '/local/custom_name/a_database/database_name_56_1118843/file_1.tgz',
    '/local/custom_name/a_database/database_name_56_1118843/file_3.tgz',
    '/local/custom_name/a_database/database_name_56_1118843/file_4.tgz',
    '/local/custom_name/a_database/database_name_56_1118843/file_2.tgz',
    '/local/custom_name/a_database/database_name_655_1118843/file_1.tgz',
    '/local/custom_name/a_database/database_name_655_1118843/file_2.tgz',
    '/local/custom_name/a_database/database_name_655_1118843/file_3.tgz',
    '/local/custom_name/a_database/database_name_655_1118843/file_4.tgz',
    '/local/custom_name_4/b_database/database_name_5242_11132428843/file_1.tgz',
    '/local/custom_name_4/b_database/database_name_5242_11132428843/file_2.tgz',
    '/shared/custom_name/c_database/database_name_56_1118843/file_1.tgz',
    '/shared/custom_name/c_database/database_name_56_1118843/file_2.tgz',
    '/local/custom_name_4/c_database/database_name_58_1118843/file_1.tgz',
    '/local/custom_name/ac_database/database_name_58_1118843/file_2.tgz',
]

def getUid(s):
    return s[1:].rpartition("/")[0].rpartition("_")[0].replace("/", "_")

result = {}
for s in l:
    result.setdefault(getUid(s), []).append(s)

print(result)
{'local_custom_name_a_database_database_name_56': ['/local/custom_name/a_database/database_name_56_1118843/file_1.tgz',
  '/local/custom_name/a_database/database_name_56_1118843/file_3.tgz',
  '/local/custom_name/a_database/database_name_56_1118843/file_4.tgz',
  '/local/custom_name/a_database/database_name_56_1118843/file_2.tgz'],
 'local_custom_name_a_database_database_name_655': ['/local/custom_name/a_database/database_name_655_1118843/file_1.tgz',
  '/local/custom_name/a_database/database_name_655_1118843/file_2.tgz',
  '/local/custom_name/a_database/database_name_655_1118843/file_3.tgz',
  '/local/custom_name/a_database/database_name_655_1118843/file_4.tgz'],
 'local_custom_name_4_b_database_database_name_5242': ['/local/custom_name_4/b_database/database_name_5242_11132428843/file_1.tgz',
  '/local/custom_name_4/b_database/database_name_5242_11132428843/file_2.tgz'],
 'shared_custom_name_c_database_database_name_56': ['/shared/custom_name/c_database/database_name_56_1118843/file_1.tgz',
  '/shared/custom_name/c_database/database_name_56_1118843/file_2.tgz'],
 'local_custom_name_4_c_database_database_name_58': ['/local/custom_name_4/c_database/database_name_58_1118843/file_1.tgz'],
 'local_custom_name_ac_database_database_name_58': ['/local/custom_name/ac_database/database_name_58_1118843/file_2.tgz']}

然后,如果需要:

transformed = [{"uid": k, "link_list": v} for k, v in result.items()]
print(transformed)
[{'uid': 'local_custom_name_a_database_database_name_56',
  'link_list': ['/local/custom_name/a_database/database_name_56_1118843/file_1.tgz',
   '/local/custom_name/a_database/database_name_56_1118843/file_3.tgz',
   '/local/custom_name/a_database/database_name_56_1118843/file_4.tgz',
   '/local/custom_name/a_database/database_name_56_1118843/file_2.tgz']},
 {'uid': 'local_custom_name_a_database_database_name_655',
  'link_list': ['/local/custom_name/a_database/database_name_655_1118843/file_1.tgz',
   '/local/custom_name/a_database/database_name_655_1118843/file_2.tgz',
   '/local/custom_name/a_database/database_name_655_1118843/file_3.tgz',
   '/local/custom_name/a_database/database_name_655_1118843/file_4.tgz']},
 {'uid': 'local_custom_name_4_b_database_database_name_5242',
  'link_list': ['/local/custom_name_4/b_database/database_name_5242_11132428843/file_1.tgz',
   '/local/custom_name_4/b_database/database_name_5242_11132428843/file_2.tgz']},
 {'uid': 'shared_custom_name_c_database_database_name_56',
  'link_list': ['/shared/custom_name/c_database/database_name_56_1118843/file_1.tgz',
   '/shared/custom_name/c_database/database_name_56_1118843/file_2.tgz']},
 {'uid': 'local_custom_name_4_c_database_database_name_58',
  'link_list': ['/local/custom_name_4/c_database/database_name_58_1118843/file_1.tgz']},
 {'uid': 'local_custom_name_ac_database_database_name_58',
  'link_list': ['/local/custom_name/ac_database/database_name_58_1118843/file_2.tgz']}]

【讨论】:

  • 解释很有意义。给我一些时间来适应这个逻辑,然后报告回来。也感谢“转换”部分。稍后我还需要从原始链接列表中进行一些其他计算,以便稍后能够访问其中的数据。原始链接列表并不简单,它实际上是一个元组列表,(link, size_in_bytes, bool1, bool2)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-20
  • 2016-06-03
  • 2020-05-27
相关资源
最近更新 更多