我在excel表中有一个包含字符串的表,比方说3列和2行。 E.g:
我想提出一种算法,可以计算整个表的校验和,如果添加一个新行(显而易见),或者即使一个字符串切换与另一行中的另一个字符串切换,也会有所不同(不太明显) )。
因此,对于下表,我们将得到与前一个不同的校验和:
我知道有很多可能的方法来实现这一目标,但是有一个干净的&在python中执行它的强大方法?我曾经考虑过将表中字符串的位置用作计算中的一个因素,但我不知道这是否是一个好主意,因为校验和计算是我较弱的技能之一。
我觉得我应该提一下,在同一个excel文件中,我有其他数据可以在不修改校验和的情况下进行更改。校验和应仅验证上述表的数据,并且必须是数值(因为我需要在之后通过CAN总线发送它)。
有没有人对我如何做到这一点有任何建议?请准确并举例说明。
修改 所以我想出了一个算法但却完全不确定它的稳健性。 我的想法是首先为第一列的每个单元格计算校验和,然后将其乘以行索引,然后对秒列和第三列进行相同的操作(如果我们使用与描述中相同的表格)。最后,通过将每个校验和乘以它们的列索引来对得到的校验和求和。如下所示:
total_checksum =(校验和('one')* 1 +校验和('four')* 2)* 1 +(校验和('two')* 1 +校验和('five')* 2)* 2 +(校验和('三')* 1 +校验和('六')* 2)* 3
我心甘情愿地发布这样的计算而没有任何花哨的代码只是为了解释我的观点。现在对于代码(目前还不是很抱歉),我们可以假设表内容已经被解析为具有key = column和item = value的字典列表。对于示例中的表,我们有:
tab = [{"A": "one", "B": "two", "C": "three"},
{"A": "four", "B": "five", "C": "six"}]
print str(calculate_checksum(tab))
def calculate_checksum(table):
"""Calculate checksum of a dictionary (represents the excel table)"""
def checksum(st):
"""Convert a string into tables of ascii characters and reduce it"""
return reduce(lambda x, y: x + y, map(ord, st))
total_cks = column_count = 0
# list the data of each column:
for column in ['A', 'B', 'C']:
data_list = [data[column] for data in tables]
chk = 0
for row_index in range(len(data_list)):
chk += checksum(data_list[row_index]) * (row_index + 1) # multiply each cell's checksum by its row index
column_count += 1
total_cks += chk * column_count # multiply each column checksum by its column index
return total_cks
使用这个算法,原始表的校验和是7254.当我切换“2”和“5”时,我得到7094所以它的工作原理。当我切换“一”和“两”时,我得到7230也被覆盖了。
答案 0 :(得分:0)
你不需要校验和。
import pandas as pd
df1 = pd.read_excel("...")
df2 = pd.read_excel("...")
exact_match = df1.equals(df2)
如果值完全匹配,则 exact_match将返回True
,否则将返回False
。
答案 1 :(得分:0)
您可以使用openpyxl python library来实现此目的。您所要做的就是遍历工作表并将累积数据存储在字符串(或您喜欢的任何格式)中以供稍后进行比较:
from openpyxl import Workbook, load_workbook
wb = load_workbook(filename = 'latest.xlsx')
sheet = wb["some_sheet"]
sheet_data = ""
i = 1
while sheet['a'+str(i)].value != None:
sheet_data = sheet['a'+str(i)].value + "::" + sheet['b'+str(i)].value + "::" + sheet['c'+str(i)].value + "\n"
i += 1
if sheet_data != old_sheet_data: #store the old_sheet_data somewhere
pass #not matched
您可以使用pip3或pip包管理器安装openpyx
库。
答案 2 :(得分:0)
在Prahlad Yeri的帮助下,我成功实现了这一目标。我发现我需要的是在zlib库中。
我将所有单元格内容添加到":"在每个字符串之间(可以使用任何其他被认为安全的字符)并使用zlib库的adler32函数来计算它的32位校验和。
import zlib
tab = [{"A": "one", "B": "two", "C": "three"},
{"A": "four", "B": "five", "C": "six"}]
print str(calculate_checksum(tab))
def calculate_checksum(table):
"""Returns a 32bits checksum out of the concatenated cell contents, using Adler algorithm."""
data = ""
for row in table:
for column in ["A", "B", "C"]:
data += row[column] + ":" # Use ":" to separate each string
return zlib.adler32(data)