Karrar Ali
Karrar Ali

Reputation: 69

Compare two lists different in two elements in the same position

I want to write a function compares two lists have the same length, the function return the two lists that are different in just two items in the same position on the list For example

If a=[0,33,2,3,4,66,9] and b=[0,22,2,3,4,77,9]

The function return those two list so because there are different in two element and every thing is the same, but if it compares: If c=[0, 2,3,33,4,66,9] And b=[0,22,2,3,4,77,9] The function should give me false results because the two items in different positions in the list

Any help would be appreciated

Upvotes: 0

Views: 3165

Answers (5)

poke
poke

Reputation: 388443

Inspired by Jon’s answer that short-circuits as soon as the threshold is met, here is a solution that is a bit simpler and does not involve some crazy itertools magic:

def no_diff_by(a, b, n):
    for x in (1 for x, y in zip(a, b) if x != y):
        n -= 1
        if n < 0:
            return False
    return True

Basically, this uses the generator feature (and Python 3’s zip—you want to use izip with Python 2) to lazily get the next non-matching pair. And for each pair, it decrements the counter by one. If we go below zero, we have found more non-matching pairs than allowed, so we can return false. Otherwise, the loop will continue until it eventually completes at which point we can return true (or the original lists if you like).

Upvotes: 2

sweet_sugar
sweet_sugar

Reputation: 1570

You can stop compare the corresponding elements if the comparison criterion is exceeded and return False. The else suite is executed after the for, but only if the for terminates normally (not by a break). Function return True if comparison exactly meet cirteria. I used the break to emphasize the action for..else, instead break here once you exit the function .

def compare(list1, list2, how_many_elements_must_differ_at_the_same_position):

    different_elements = 0

    for x, y in zip(list1, list2):
        if x != y:
            different_elements += 1
            if different_elements > how_many_elements_must_differ_at_the_same_position:
                break
    else:
        if different_elements == how_many_elements_must_differ_at_the_same_position:
            return True
        else:
            return False

    return False

Upvotes: 1

Jon Clements
Jon Clements

Reputation: 142256

You can also do this lazily... and stop at the first n many that don't match - so if you had massive iterables, you can stop as soon as you determine there's been too many mis-matches - rather than process all of them, then see if the threshold has been exceeded, eg:

from itertools import islice, izip

def no_diff_by(a, b, n):
    not_equal = (False for x, y in izip(a, b) if x != y)
    return next(islice(not_equal, n, None), True)

The way this works:

  • build a generator that returns False for each non-equal value between the two iterables
  • By using islice(not_equal, n, None) and calling next on it, we attempt to access the nth value from the above generator
    • Where a value is accessible - it means that there's been too many Falses - so the lists have exceeded the threshold to match - so we return the value of False (the nth item - since the entire generator only returns False)
    • Where a value isn't accessible then next returns the default value of True instead of raising a StopIteration - that means we haven't exceeded the threshold...

Upvotes: 4

Anupam
Anupam

Reputation: 717

you can do it by list comprehension,,

def comp_by_2_places(list1, list2):
    return True if len([False for x,y in zip(a,b) if x != y])== 2 else False

hope it helps,,,

Upvotes: 0

Francis Colas
Francis Colas

Reputation: 3647

Well, my approach would be to count the number of difference and then to check it is less or equal than 2. To count, you can use several ways: a for loop with a counter, the length of the list of differences, or even the sum of a list with 1 if the elements are different:

def weird_cmp(list1, list2):
    if len(list1) != len(list2):
        return False
    number_of_differences = sum(1 for e1, e2 in zip(list1, list2) if e1 != e2)
    return number_of_differences <= 2

Upvotes: 0

Related Questions