【问题标题】:Python - Comparison of list of lists with approximating floatsPython - 列表列表与近似浮点数的比较
【发布时间】:2017-08-20 09:56:23
【问题描述】:

我对编程有点陌生,我想比较 python 中的两个列表列表,而这些列表中的浮点数可能有错误。举个例子:

first_list = [['ATOM', 'N', 'SER', -1.081, -16.465,  17.224], 
              ['ATOM', 'C', 'SER', 2.805, -3.504,  6.222], 
              ['ATOM', 'O', 'SER', -17.749, 16.241,  -1.333]]

secnd_list = [['ATOM', 'N', 'SER', -1.082, -16.465,  17.227],
              ['ATOM', 'C', 'SER', 2.142, -3.914,  6.222], 
              ['ATOM', 'O', 'SER', -17.541, -16.241,  -1.334]]

预期输出:

Differences = ['ATOM', 'C', 'SER', 2.805, -3.504,  6.222]

到目前为止我的尝试:

def aprox (x, y):
    if x == float and y == float:
        delta = 0.2 >= abs(x - y)
        return delta
    else: rest = x, y
    return rest

def compare (data1, data2):
    diff = [x for x,y in first_list if x not in secnd_list and aprox(x,y)] + [x for x,y in secnd_list if x not in first_list and aprox(x,y)]
    return diff

或者在元组的帮助下,但我不知道如何建立近似值:

def compare (data1, data2):
    first_set = set(map(tuple, data1))
    secnd_set = set(map(tuple, data2))
    diff = first_set.symmetric_difference(secnd_set)
    return diff

希望你能帮助我! :)

【问题讨论】:

  • 您最初的 compare 函数具有参数 data1data2,但随后您引用了(全局?)对象 first_listsecnd_list 并且从不使用参数。
  • fyi isinstance(x, float) 是你应该如何检查号码类型
  • 您的预期输出错误,应该是 2 行,因为根据您的代码,有 2 行的差异大于 0.2。

标签: python list compare


【解决方案1】:

线

if x == float and y == float

不准确... 检查变量类型的正确方法是使用type() 函数... 尝试用

替换上面的行
if type(x) is float and type(y) is float:

【讨论】:

    【解决方案2】:

    这有点笨拙,但我是即时完成的,它应该可以为您带来想要的结果。正如我在您的代码中提到的,您将阈值设置为0.2,这意味着应该返回两行,而不是像您提到的那样。

    def discrepancies(x, y):
        for _, (row1, row2) in enumerate(zip(x, y)):
            for _, (item1, item2) in enumerate(zip(row1[3:],row2[3:])):
                if abs(item1 - item2) >= 0.2:
                    print row1
                    break
    
    discrepancies(first_list, secnd_list)
    ['ATOM', 'C', 'SER', 2.805, -3.504, 6.222]
    ['ATOM', 'O', 'SER', -17.749, 16.241, -1.333]
    

    几个警告,这会变得相当慢,因为每个 for 循环都会增加 O(n) 并且对于列表中较大的列表,我会使用 itertools.izip 函数,我相信它被调用了。希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      也许您可以遍历两者中的每个元素,然后比较子元素: 然后,当任何子元素不相等时,可以根据其类型将其添加到结果中,即如果两个 字符串不相等,它可以添加到结果中,或者如果它是浮点数并且math.isclose() 可以用于近似:

      注意:已进行更正以匹配预期输出,first_list 的第三个元素中缺少负号

      import math
      
      first_list = [['ATOM', 'N', 'SER', -1.081, -16.465,  17.224], 
                    ['ATOM', 'C', 'SER', 2.805, -3.504,  6.222], 
                    ['ATOM', 'O', 'SER', -17.749, -16.241,  -1.333]] # changes made
      
      secnd_list = [['ATOM', 'N', 'SER', -1.082, -16.465,  17.227],
                    ['ATOM', 'C', 'SER', 2.142, -3.914,  6.222], 
                    ['ATOM', 'O', 'SER', -17.541, -16.241,  -1.334]]
      
      diff = []
      for e1, e2 in zip(first_list, secnd_list):
          for e_sub1, e_sub2 in zip(e1, e2):
              # if sub-elements are not equal
              if e_sub1 != e_sub2:
                  # if it is string and not equal
                  if isinstance(e_sub1, str):
                      diff.append(e1)
                      break # one element not equal so no need to iterate other sub-elements
                  else:  # is float and not equal
                      # Comparison made to 0.2
                      if not math.isclose(e_sub1, e_sub2, rel_tol=2e-1):
                          diff.append(e1)
                          break # one element not equal so no need to iterate other sub-elements
      diff
      

      输出:

      [['ATOM', 'C', 'SER', 2.805, -3.504, 6.222]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多