【问题标题】:Comparing a list of different sizes and data to output the difference比较不同大小和数据的列表以输出差异
【发布时间】:2015-10-23 14:47:23
【问题描述】:

我正在为个人项目开发一个程序,以更好地了解 Python 中的列表和字典是如何工作的。我是一个业余程序员,还在学习。该程序的目标是能够读取两个文件并将这两个文件的参数相互比较,如果其中一个文件的参数不正确或不匹配,它将使用不正确/不匹配的参数创建一个新文件.

我已经创建了这个并且程序会按照它的假设进行操作。但是,在尝试比较具有比比较文件更多或更少参数的文件时,我遇到了错误。简而言之,我正在相互比较的列表具有相同数量的元素。但是,如果列表的元素不相等,我会遇到错误,通常是列表索引超出范围。

尽我所能,它的要点如下: 我有 2 个文本文档:
文本A.txt:

Data1="123.212.2.312"
Dog=12
Cat="127.0.0.1"
Data2=9498
Fish=""
Tiger=9495
Data3=5
Data4=2
Game=55
Tree=280
Falcon=67
Bear=2

TextB.txt:

Dog=123
Cat="127.0.0.1"
Data2=9498
Eagle=""
Tiger=9495
Data3=5
Data4=2
Rock=52
Mountain=380
Falcon=627

正如我们所见,两个文本文档中都缺少参数,并且两者中的一些参数都不正确,所以我想将 textA.txt ONLY 的差异输出到另一个文本文档中.

因此程序将执行以下操作:(这是当前程序在比较具有相同个参数的两个文本时的工作方式,请使用此流程图盐的意思并不完全代表程序,只是大致了解程序的工作原理)

所以最后我的输出应该是:

请记住,我不关心 TextB.txt 中是否存在参数,但 textA.txt 中不存在;我关心的是,如果一个参数存在于 textA.txt 而不是 textB.txt 令人困惑我知道,但希望图片能把事情弄清楚。

至于我的代码,这是一段很长的代码,但重要的部分如下:请注意我也在使用 PYQT4 作为 gui。

with open(compareResults, 'wb') as fdout:
            for index, tabName in enumerate(setNames):
                tabWidget = QtGui.QWidget()
                tabLabel = QtGui.QTextEdit()
                print "Tab Name is :{}".format(tabName)
                fdout.write('{}'.format(tabName) + '\r\n')
                nameData = lst[index]
                print 'name data = {}'.format(nameData)
                for k in nameData:
                    if nameData[k] != correct_parameters[k]:
                        tabLabel.setTextColor(QtGui.QColor("Red"))
                        tabLabel.append('This Parameter is Incorrect: {} = {}'.format(k, nameData[k]))
                        fdout.write('\t' + '|' + 'This Parameter is Incorrect: {} = {}'.format(k, nameData[k]) + '\t' + '|' + '\r\n')
                        print ('{} = {}'.format(k, nameData[k]))
                    elif nameData[k] == correct_parameters[k]:
                        tabLabel.setTextColor(QtGui.QColor("Black"))
                        tabLabel.append('{} = {}'.format(k, nameData[k]))
                        fdout.write('\t' + '|' + '{} = {}'.format(k, nameData[k]) + '\t' + '|' + '\r\n')
                        print ('{} = {}'.format(k, nameData[k]))
                tabLayout = QtGui.QVBoxLayout()
                tabLayout.addWidget(tabLabel)
                tabWidget.setLayout(tabLayout)
                self.tabWidget.addTab(tabWidget, tabName)

我相信我对代码的缺点是我循环了一组元素,并且在循环两个列表时期望相同​​数量的元素。当它们没有相同数量的元素时,我如何能够循环遍历列表?

如果问题太混乱或者您需要更多信息/代码,请告诉我,我会编辑问题。

编辑:只是为了澄清我最终使用了@CarsonCrane 的答案,因为它帮助我创建了我需要的循环,这就是我的代码现在的样子:

for k in nameData:
    if k in correct_parameters:
        if nameData[k] != correct_parameters[k]:
            tabLabel.setTextColor(QtGui.QColor("Red"))
            tabLabel.append('This Parameter is Incorrect: {} = {}'.format(k, nameData[k]))
            fdout.write('\t' + '|' + 'This Parameter is Incorrect: {} = {}'.format(k, nameData[k]) + '\t' + '|' + '\r\n')
            print ('{} = {}'.format(k, nameData[k]))
        elif nameData[k] == correct_parameters[k]:
            tabLabel.setTextColor(QtGui.QColor("Black"))
            tabLabel.append('{} = {}'.format(k, nameData[k]))
            fdout.write('\t' + '|' + '{} = {}'.format(k, nameData[k]) + '\t' + '|' + '\r\n')
            print ('{} = {}'.format(k, nameData[k]))
    else:
        tabLabel.setTextColor(QtGui.QColor("Blue"))
        tabLabel.append('{} = {} does not appear in our default'.format(k, nameData[k]))
        fdout.write('\t' + '|' + '{} = {} does not appear in our default'.format(k, nameData[k]) + '\t' + '|' + '\r\n')
        print ('{} = {} does not appear in our default'.format(k, nameData[k]))

【问题讨论】:

  • 这是相当广泛的,但基本上你想要做的是将文件读入两个字典,循环遍历文本 A 字典中的 items,然后检查文本 B 的字典以查看如果它具有您要查找的元素以及值是否相同。
  • 基本上是的,这个想法是,如果文本 A 中存在 item,则将相同的 item 与文本 B 中的 item 进行比较。如果文本 A 中的 item 不存在于文本 B 然后在已经比较的顶部打印“嘿item 文本 B 中不存在”以查看它们是否相似。

标签: python list dictionary compare


【解决方案1】:

创建两个字典并将文件的值解析为字典的相应键和值。循环遍历第一个字典并比较值。

d1 = {"Tiger":9495, "Data3":5, "Data4":2}
d2 = {"Tiger":94, "Data4":2}

for key, value in d1.items():
    if key in d2:
        if value == d2[key]:
            #same thing
        else:
            #different
    else:
        #d2 doesn't have key

【讨论】:

  • 由于None 不会来自文件,您可以简化为if value == d2.get(key):
  • 好点,但似乎 OP 想要为这两种情况提供不同的行为。
【解决方案2】:

您程序中的根本问题是找出两个序列之间的差异,这是最长公共子序列问题(LCS,参见https://en.wikipedia.org/wiki/Longest_common_subsequence_problem)的推导。 它的解决方案并不简单。在Python中你可以使用difflib库来处理这类问题。

# Assuming you have already parsed the files into two lists

from difflib import SequenceMatcher, Differ
params1 = [
    ('Data1', '123.212.2.312'),
    ('Dog', 12),
    ('Cat', '127.0.0.1'),
    ('Data2', 9498),
    ('Fish', ''),
    ('Tiger', 9495),
    ('Data3', 5),
    ('Data4', 2),
    ('Game', 55),
    ('Tree', 280),
    ('Falcon', 67),
    ('Bear', 2)
]
params2 = [
    ('Dog', 123),
    ('Cat', '127.0.0.1'),
    ('Data2', 9498),
    ('Eagle', ''),
    ('Tiger', 9495),
    ('Data3', 5),
    ('Data4', 2),
    ('Rock', 52),
    ('Mountain', 380),
    ('Falcon', 627)
]

# If the order of the entries in the file is not mandatory you could sort the lists
matcher = SequenceMatcher(None, params1, params2)
if matcher.ratio() != 1:
    print 'Sequences are not equal'
    print list(Differ().compare(params1, params2)) # Prints the difference

您还可以通过以下方式获取将params1 转换为params2 的操作:

matcher.get_opcodes()

或匹配的块:

matcher.get_matching_blocks()

有了这些数据,您只需做一些工作即可在屏幕上显示差异。

【讨论】:

    【解决方案3】:

    您将从几件事中受益匪浅。首先,您可以使用以下方式从每个文件快速创建字典:

    d1 = dict(l.strip().split('=') for l in open('file1.txt'))
    

    这将为您提供一种更简洁的方式来访问您的个人价值观。接下来,在比较两个字典时,这样的事情是相当合理的:

    for key, value in d1.items():
      if key not in d2:
        print "Key '%s' from d1 not in d2" % key
        continue
      value2 = d2[key]
      # other comparison / output code here
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-05
      • 1970-01-01
      • 1970-01-01
      • 2013-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多