【问题标题】:Compare two lists of unequal length and non-matching values比较两个长度不等且不匹配的值列表
【发布时间】:2016-10-25 14:36:00
【问题描述】:

我想比较两个包含不同长度的匹配整数的列表。目标是通过根据较短列表中的缺失值从较长列表中删除项目来使它们具有相同的长度。名单:

list1 = [101, 201, 301, 402, 502, 603, 701, 802, 904, 10012, 10021, 10033, 10041, 10054, 10062, 10071, 10082, 10093, 10101]
list2 = [102, 203, 504, 601, 703, 901, 10013, 10071, 10082, 10093, 10103]

但是,两个列表的匹配值并不完全相同,在此示例中可以在 0 和 3 之间变化。

结果如下所示:

resultlist1 = [101, 201, 502, 603, 701, 904, 10012, 10073, 10082, 10093, 10101]
resultlist2 = [102, 203, 504, 601, 703, 901, 10013, 10071, 10082, 10093, 10103]

removed_items_list1 = [2, 3, 7, 10, 11, 12, 13, 14]  # Index numbers of 

我尝试了以下但没有成功

set(list1).intersection(list2)

只返回完全匹配

for i in xrange(len(list2)):
    if abs(list1[i] - list2[i]) > 3:
        del list1[i]

不删除所有不需要的值

我将如何比较这两个长度不等的列表并删除较长列表中的不匹配项(在一定变化范围内)?

【问题讨论】:

    标签: python list


    【解决方案1】:

    这是一个需要线性时间的解决方案;其他的需要二次时间,但如果您的输入很小,这可能会很好。

    def align(shorter, longer, margin=3):    
        result = []
        removed = []
    
        longer = enumerate(longer)
    
        for target in shorter:
            while True:
                index, current = next(longer)
                if abs(current - target) <= margin:
                    result.append(current)
                    break
                else:
                    removed.append(index)
    
        return result, removed
    

    这假定您始终可以像示例中那样对齐列表。如果这不是真的,您需要在上面添加一些错误检查。

    例子:

    >>> align(list2, list1)
    ([101, 201, 502, 603, 701, 904, 10012, 10071, 10082, 10093, 10101],
     [2, 3, 7, 10, 11, 12, 13, 14])
    

    【讨论】:

    • 对于一定长度,线性仍然可能比二次方花费更长的时间。因此,如果有人有时间,比较不同方法的性能会很有趣:)
    • 非常正确,因此是“如果输入很小”的免责声明。但最终列表推导仅比 Python 中的 for-loop 快一点,因此上述解决方案的隐藏常量至少与推导解决方案的隐藏常量相当。我没有进行任何测试,但我的猜测是,当列表有几百个条目时,您会开始看到真正的不同。
    • 我喜欢你的解决方案。我使用了大约 1200 个条目的列表。但是,当我使用你的函数时,我得到一个 StopIteration 错误:index, current = next(longer)
    • @cf2 这意味着您的列表没有像您的示例那样对齐。换句话说,我们不能通过仅从较大的条目中取出条目直到它们在较低的边距内来使它们具有相同的长度。例如,此输入会给出错误:longer = [1, 2, 9, 9, 9, 9]shorter = [1, 2, 3],边距为 3
    【解决方案2】:

    可以使用numpy数组比较:

    list1 = [101, 201, 301, 402, 502, 603, 701, 802, 904, 10012, 10021, 10033, 10041, 10054, 10062, 10071, 10082, 10093, 10101]
    list2 = [102, 203, 504, 601, 703, 901, 10013, 10071, 10082, 10093, 10103]
    import numpy as np
    l1 = np.array(list1)
    l2 = np.array(list2)
    
    ind = abs(l1 - l2[:,None]) <= 3
    
    print l1[ind.max(0)]
    print l2[ind.max(1)]
    print ind.max(1)
    print ind.max(0)
    print np.where(~(ind.max(0)))
    

    结果

    [  101   201   502   603   701   904 10012 10071 10082 10093 10101]
    
    [  102   203   504   601   703   901 10013 10071 10082 10093 10103]
    
    [ True  True  True  True  True  True  True  True  True  True  True]
    
    [ True  True False False  True  True  True False  True  True False False
     False False False  True  True  True  True]
    
    (array([ 2,  3,  7, 10, 11, 12, 13, 14]),)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-24
      • 1970-01-01
      • 2015-04-16
      相关资源
      最近更新 更多