打印出列表每行的已更改列的索引

时间:2015-08-06 12:20:33

标签: python list

以下循环扫描匹配ID(索引0)的两个列表(源和主),然后对于ID匹配的那一行,它会查看已更改的列并打印它们:

        for row in source:
            identifier = row[0]
            new_cols = row[1:]
            for row in master:
                old_cols = row[1:]
                if identifier == row[0]:
                    print(row[0]) # ID that matched
                    changed_cols = [col for col in new_cols if col not in old_cols] 
                    print(changed_cols) # cols that differ

列表每行包含超过20列,所以我认为使用行[1:]会很聪明,但我不确定如何使用此方法来获取更改列的索引。谢谢你的帮助。

更新

source = [['1002', '', '', '', '13RA11', '', 'LO', '4302', '99111', '0', ''], 
['1076', '', '', '', '13RA11', '', 'LO', '4302', '999111', '0', ''], 
['1130', '', '', '', '11HOT1A', '', 'LO', '4302', '99111', '0', '']]

master = [['1002', '', '', '', '13RA11', '', 'LO', '4302', '99111', '0', ''], 
['1076', '', '', '', '13RA11', '', 'LO', '4302', '999111', '1', ''], 
['1130', '', '', '', '13RA11', '', 'LO', '4302', '99111', '1', '']]

3 个答案:

答案 0 :(得分:1)

尝试创建过滤器并使用zip将每个匹配的行折叠在一起(例如,将源和主行中的行压缩在一起,以匹配ID。)

# A generator that returns True/False based on items matching.
def bool_gen(zipped):
    for tup in zipped:
        yield tup[0] == tup[1]

# Use enumerate to store columns as you iterate over the generator.
for enum, item in enumerate(bool_gen(zip(source_row1, master_row1))):
    if (item == True):
        # Print the matching index.
        print(enum)

对于source_row1 = [1,6,3,8], master_row1 = [5,6,7,8],这会打印索引1和3.如果需要,您还可以将整个内容放在列表解析中,如下所示:

changed_cols = [enum for enum, item in enumerate(bool_gen(zip(source_row1, master_row1))) if (item == True)]
# changed_cols returns [1, 3]

将此建议用于您的代码:

for row in source:
    identifier = row[0]
    new_cols = row[1:]
    for row in master:
        old_cols = row[1:]
        if identifier == row[0]:
            print(row[0]) # ID that matched
            changed_cols = [enum for enum, item in enumerate(bool_gen(zip(new_cols, old_cols))) if (item == True)]
            print(changed_cols) # cols that differ

但是,正如您所看到的,它不会减少所需的代码量,也不会使其更具可读性。我不确定哪个代码会更有效率。

如果我们的答案不合适,请告诉我们。如果是这样,请在问题中添加更多详细信息。

答案 1 :(得分:1)

您是否考虑过使用enumerate?您的列表理解将改为:

changed_cols = [(ID,col) for ID,col in enumerate(new_cols) if col not in old_cols]

这对我来说似乎是最简单的解决方案。

如果我误解了您的问题,请告诉我,我会努力调整我的解决方案:)

编辑:我想你可能想要像Gary建议的那样:

changed_cols = [(ID,col) for ID,col in enumerate(new_cols) if col != old_cols[ID]]

这将仅比较每个新列的相应旧列。我猜这是你真正想要的功能。如果您不确定区别,请告诉我:))

答案 2 :(得分:1)

您应该保留列号以进行比较。如果不这样做,则不会检测到2列之间的交换。你可以这样做:

for row in source:
    identifier = row[0]
    new_cols = row[1:]
    for row in master:
        if identifier == row[0]:
            old_cols = row[1:]
            print(row[0]) # ID that matched
            n = len(new_cols) if len(new_cols) <= len(old_cols) else len(old_cols)
            changed_cols = [(i, old_cols[i], new_col[i]) for i in range(n) if new_cols[i] != old_cols[i ]] 
            print(changed_cols) # cols that differ
            if len(new_cols) < len(old_cols): print(len(old_cols)-len(new_cols), " cols missing")
            if len(new_cols) > len(old_cols): print(len(new_cols)-len(old_cols), " cols added")