pythonlistepsilonlist-comparisonfloating-point-comparison

How to compare multiple lists for numerical closeness two at a time?


Say I have 4 lists:

A = [1.1, 1.4, 2.1, 2.4]
B = [1.3, 6.5, -1.0, 2.3]
C = [0.5, -1.0, -1.1, 2.0]
D = [1.5, 6.3, 2.2, 3.0]

How do I 1)compare the lists eg A,B B,C C,D A,C so on and 2)return true if the elements are +/-0.2 ?

Example output: (Or any other way to represent the data)
A,B [true, false, false, true]
B,C [false, false, true, false]

My thoughts are to append the lists have a for loop to iterate through all.

A.append(B)
A.append(C)
.
.

But then I'm stuck since if I do

for x in A:
    for y in A[x]:
        if A[x][y] - A[x+1][y] <= 0.2
            if A[x+1][y] - A[x][y] <= 0.2

Obviously it doesn't work. Are there ways to iterate through the lists without duplicates and compare at the same time?

Thanks in advance


Solution

  • Update:

    OK, now I think I understand both questions you're asking:

    from itertools import combinations
    
    A = [1.1, 1.4, 2.1, 2.4]
    B = [1.3, 6.5, -1.0, 2.3]
    C = [0.5, -1.0, -1.1, 2.0]
    D = [1.5, 6.3, 2.2, 3.0]
    lists = {'A': A, 'B': B, 'C': C, 'D': D}
    tol = 0.2
    
    def compare_lists(a, b, tol):
        return [abs(elem1-elem2) <= tol for elem1, elem2 in zip(a, b)]  # Might want '<' instead
    
    for name1, name2 in combinations(lists.keys(), 2):
        a, b = lists[name1], lists[name2]
        print('{}, {} {}'.format(name1, name2, compare_lists(a, b, tol)))
    

    Output:

    A, B [True, False, False, True]
    A, C [False, False, False, False]
    A, D [False, False, True, False]
    B, C [False, False, True, False]
    B, D [True, False, False, False]
    C, D [False, False, False, False]
    

    Update 2:

    To answer your follow up question, if the lists are actually members of a list-of-lists, you could similarly do something like this:

    # An alternative for when the lists are nested inside another list
    
    from itertools import combinations
    
    lists = [
        [1.1, 1.4, 2.1, 2.4],
        [1.3, 6.5, -1.0, 2.3],
        [0.5, -1.0, -1.1, 2.0],
        [1.5, 6.3, 2.2, 3.0]
    ]
    tol = 0.2
    
    def compare_lists(a, b, tol):  # unchanged
        return [abs(elem1-elem2) <= tol for elem1, elem2 in zip(a, b)]  # Might want '<' instead
    
    for i, j in combinations(range(len(lists)), 2):  # all combinations of pairs of indices
        a, b = lists[i], lists[j]
        print('{}[{}], [{}] {}'.format('lists', i, j, compare_lists(a, b, tol)))
    

    Output:

    lists[0], [1] [True, False, False, True]
    lists[0], [2] [False, False, False, False]
    lists[0], [3] [False, False, True, False]
    lists[1], [2] [False, False, True, False]
    lists[1], [3] [True, False, False, False]
    lists[2], [3] [False, False, False, False]