【问题标题】:Wrong logic in nested 'if' in a Python for-loopPython for循环中嵌套'if'中的错误逻辑
【发布时间】:2014-09-05 07:24:46
【问题描述】:

我有一个脚本来读取 Excel 文件,其中单元格 A1 ~ A6 包含:

OK 17
OK 9
BKK 17
OK 16
OK 12
BKK 16

它们是 Excel 文件的唯一内容。

我要做的是检查单元格中的代码“OK”或“BKK”,并告诉我单元格中的代码是否与上面那一行相同。

例如,第 2 行有 'OK',这与第 1 行有 'OK' 相同,所以它会告诉我 'OK found' 和 'row no.2 and 1 found same code'。

但是下面运行的结果跳过了一些行:

from xlrd import open_workbook

the_file = open_workbook('c:\\file.xls',formatting_info=True)
the_sheet = the_file.sheet_by_index(0) 

for row in range(0, the_sheet.nrows):
    a = the_sheet.cell(row, 0).value
    above_a = the_sheet.cell(row-1, 0).value
    if a[0:2] == above_a[0:2]:
        print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code'
        if 'OK' in a:
            print 'OK found'
        else:
            print 'BKK found'

结果是:

row no.2 and 1 found same code
OK found
row no.5 and 4 found same code
OK found

逻辑错了。

澄清

有 6 个值要检查,所以我预计有 6 个结果,但只有 4 个。2 个被跳过。

可以这样算,但是有没有办法简化呢?

for row in range(0, the_sheet.nrows):
    a = the_sheet.cell(row, 0).value
    above_a = the_sheet.cell(row-1, 0).value
    if a[0:2] == above_a[0:2] and 'OK' in a:
        print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code' + ' OK found'
    if a[0:2] == above_a[0:2] and 'BKK' in a:
        print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code' + ' BKK found'
    if a[0:2] != above_a[0:2] and 'BKK' in a:
        print 'BKK found'

    if a[0:2] != above_a[0:2] and 'OK' in a:
        print 'OK found'

【问题讨论】:

  • 代码根据您的描述打印正确的内容。什么不见​​了?如果 a 和 above_a 不相等,则不会打印任何内容。这就是你所说的跳过行的意思吗?另外,做 range(1,brows) 因为第一行永远不会匹配。
  • 感谢 tdelaney。有 6 个值要通过,但结果只有 4 个。我的意思是缺少 2 个......
  • 你的外部 if 需要一个带有打印语句的 else 子句。这将为每一行显示一些内容。

标签: python if-statement for-loop


【解决方案1】:

我不确定您的代码是否真的跳过了行。找不到匹配项时,您只是不打印任何内容。如果您将else 添加到外部if 循环中,如下所示:

from xlrd import open_workbook

the_file = open_workbook('c:\\file.xls',formatting_info=True)
the_sheet = the_file.sheet_by_index(0) 

for row in range(0, the_sheet.nrows):
    a = the_sheet.cell(row, 0).value
    above_a = the_sheet.cell(row-1, 0).value
    if a[0:2] == above_a[0:2]:
        print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code'
        if 'OK' in a:
            print 'OK found'
        else:
            print 'BKK found'
    else:
        print 'row no.' + str(row + 1) + ' and ' + str(row) + ' do not match'

你应该得到以下结果:

row no.1 and 0 do not match
row no.2 and 1 found same code
OK found
row no.3 and 2 do not match
row no.4 and 3 do not match
row no.5 and 4 found same code
OK found
row no.6 and 5 do not match

更大的问题是您从第一行开始将一行与上面的行进行比较(因为 for 循环中的范围是从 0 到 5)。所以第一个比较是在“OK 17”和“BKK 16”之间(即第 0 行和第 -1 行)。如果您注释掉if 循环并在for 循环中告诉python print a, above_a,您应该能够看到这一点。

for row in range(0, the_sheet.nrows):
    a = the_sheet.cell(row, 0).value
    above_a = the_sheet.cell(row-1, 0).value

    print a, above_a

就行索引而言,您正在比较以下 (a, above_a):

0 -1
1 0
2 1
3 2
4 3
5 4

您可以通过从 0 开始并与下面的行进行比较来解决此问题,或者更简单地说,从 1 开始您的 for 循环。这将为您提供以下结果:

row no.2 and 1 found same code
OK found
row no.3 and 2 do not match
row no.4 and 3 do not match
row no.5 and 4 found same code
OK found
row no.6 and 5 do not match

================================================ ====================================

解决您的编辑问题:

for 循环的第二个版本做得更好,因为它包含了不匹配的情况。但是您仍然从 0 开始您的范围,因此它将第一行(索引 0)与最后一行(索引 -1)进行比较。这并不理想。

关于简化新 for 循环中的 if 语句,您可以使用 elifelse 代替四个 if 语句。您还可以将最后两个 if 语句更改为单个 else 并嵌套一个 if 以测试该行中是否包含“OK”或“BKK”。以下代码为示例:

for row in range(1, the_sheet.nrows):
    a = the_sheet.cell(row, 0).value
    above_a = the_sheet.cell(row-1, 0).value
    if a[0:2] == above_a[0:2] and 'OK' in a:
        print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code' + ' OK found'
    elif a[0:2] == above_a[0:2] and 'BKK' in a:
        print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code' + ' BKK found'
    else:
        if 'BKK' in a:
            print 'BKK found in row %d' % row
        else:
            print 'OK found in row %d' % row

还有一个问题需要解决。上面的代码只给你 5 个结果。听起来您想知道两个不同的事情:

  1. 单元格的内容是否包含“OK”或“BKK”?
  2. 单元格的内容是否与其上方单元格的内容相匹配 关于第一个问题?

您可能遇到的问题是第一个问题涉及 6 个答案,但第二个问题仅涉及 5 个。第一行上面没有一行,因此没有第二个问题的答案。您可以更改代码以分别回答每个问题,或者将两个问题组合成一个打印语句,其中包括除第一行之外的每一行的比较。

如果我误解了您要回答的问题,请进一步澄清。

【讨论】:

  • 预览时,tdelaney 说得更简洁快速
  • ...但是@user3684695 举了一个例子,知道行-1 包裹到单元格的另一端,所以我认为(s)/他应该在这里获胜。
  • 谢谢,user3684695。非常感谢您的帮助和分析精神!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-16
  • 1970-01-01
相关资源
最近更新 更多