Openpyxl 和二进制搜索

Openpyxl and Binary Search

问题:我有两个传播sheet。 Spreadsheet 1 有大约 20,000 行。 Spreadsheet 2 有近 100 万行。当 spreadsheet 1 中一行的值与 spreadsheet 2 中一行的值匹配时,spreadsheet 2 中的整行被写入 excel。题目不是太难,但是行数如此之多,运行时间长得令人难以置信。

第 1 本书示例: |键|值| |------|--------------------| |397241|587727227839578000|

第 2 本书的示例:

ID a b c
587727227839578000 393 24 0.43

我目前的解决方案是:


g1 = openpyxl.load_workbook('path/to/sheet/sheet1.xlsx',read_only=True)
grid1 = g1.active
grid1_rows = list(grid1.rows)

g2 = openpyxl.load_workbook('path/to/sheet2/sheet2.xlsx',read_only=True)
grid2 = g2.active
grid2_rows = list(grid2.rows)

for row in grid1_rows:
        value1 = int(row[1].value)
        print(value1)
        for row2 in grid2_rows:
            value2 = int(row2[0].value)
            if value1 == value2:
                new_Name = int(row[0].value)
                print("match")
                output_file.write(str(new_Name))
                output_file.write(",")
                output_file.write(",".join(str(c.value) for c in row2[1:]))
                output_file.write("\n")

这个解决方案有效,但 运行时间又是荒谬的。理想情况下,我想取 value1(来自第一个 sheet,)然后在另一个 sheet 上对该值执行二进制搜索,然后就像我当前的解决方案一样,如果匹配,则复制整行到一个新文件。那么就

如果有更快的方法来做到这一点,我会洗耳恭听。我在 python 方面不是最出色的,因此我们将不胜感激。 谢谢

你在这里被踢屁股是因为你使用了不合适的数据结构,这需要你使用嵌套循环。

下面的示例使用 sets 来匹配从第一个 sheet 到第二个 sheet 的索引。这 假设 在两个 sheet 上都没有重复项,根据您的问题描述,这看起来很奇怪。一旦我们从两个 sheet 中创建了索引集,我们需要做的就是将这两个集相交以找到 sheet 2.

上的索引集

然后我们有比赛,但我们可以做得更好。如果我们将第二个 sheet 行数据放入以索引为键的字典中,那么我们可以在进行匹配时保留行数据,而不必在与集合相交后去寻找匹配的索引。

我还放入了一个枚举,可能需要也可能不需要它来确定传播sheet 中的哪些行是感兴趣的行。可能不需要。

加载完成后,这应该会在眨眼间执行。如果你开始有内存问题,你可能只想在开始时构建字典而不是列表字典。

第 1 本书:

第 2 本书:

代码:

import openpyxl

g1 = openpyxl.load_workbook('Book1.xlsx',read_only=True)
grid1 = g1.active
grid1_rows = list(grid1.rows)[1:]  # exclude the header

g2 = openpyxl.load_workbook('Book2.xlsx',read_only=True)
grid2 = g2.active
grid2_rows = list(grid2.rows)[1:]  # exclude the header

# make a set of the values in Book 1 that we want to search for...

search_items = {int(t[0].value) for t in grid1_rows}
#print(search_items)

# make a dictionary (key-value paring) for the items in the 2nd book, and
# include an enumeration so we can capture the row number

lookup_dict = {int(t[0].value) : (idx, t) for idx,t in enumerate(grid2_rows, start=1)}

#print(lookup_dict)

# now let's intersect the set of search items and key values to get the keys of the matches...

keys = search_items & lookup_dict.keys()

#print(keys)

for key in keys:
    idx = lookup_dict.get(key)[0]       # the row index, if needed
    row_data = lookup_dict.get(key)[1]  # the row data
    print(f'row {idx} matched value {key} and has data:')
    print(f'  name: {row_data[1].value:10s} \t qty: {int(row_data[2].value)}')

输出:

row 3 matched value 202 and has data:
  name: steak        qty: 3
row 1 matched value 455 and has data:
  name: dogfood      qty: 10