3

The challange is to write a function to compare two rather small lists of integers (mostly less than 10 elements each). One list could be something like:

self = [0, 0, 1, 2]

The lists which it is to be compared with could look like one of the following examples:

other1 = []
other2 = [0, 0, 1]
other3 = [0, 0, 1, 2, 0]
other4 = [0, 1, 1, 2]
other5 = something

As you can see, duplicate elements are quite common and the order of elements is important.

The expected result should be an integer, representing how long self and other are the same, counted from the beginning. So depending on other, the result would be:

result1 = 0
result2 = 3
result3 = 4
result4 = 1
result5 = 0

The code should be most efficient, since it is to be used some 100 times for every user interaction.

I coded the following, it works as desired, but seems to be kind of slow:

def match(self, other):
    if self == other:
        return len(self)
    element = -1
    for element in range(min(len(self),  len(other))):
        if self[element] != other[element]:
            element -= 1
            break
    return element +1

The first if statement is already an enhancement to speed things up, but the solution still seems slow and also looks a bit clumsy with all its corrections to the variable named element and the two return statements.

Has anybody a name for such a function which is better than 'match' or 'compare'?

Richard
  • 85
  • 1
  • 7

3 Answers3

4
>>> from itertools import takewhile, izip
>>> def F(seq1, seq2):
        return sum(1 for x in takewhile(lambda x: x[0] == x[1], izip(seq1, seq2)))

>>> F([0, 0, 1, 2], [0, 0, 1, 2, 0])
4
jamylak
  • 128,818
  • 30
  • 231
  • 230
  • The documentation to it is found at http://docs.python.org/2/library/collections.html and http://docs.python.org/2/library/itertools.html – Richard Mar 17 '13 at 09:50
  • Surprising performance results: http://stackoverflow.com/questions/15477314/performance-of-library-itertools-compared-to-python-code – Richard Mar 18 '13 at 12:54
  • @Richard I didn't expect this to be fastest in raw speed, I wrote it for clarity purposes but it is written as the fastest possible algorithm, I agree with the other answers that clarity is most important. If you wanna fully optimise the runtime just write it in C. Also as you can see in the other answers there are always tweaks you can do to make python faster but I always prefer elegant code. – jamylak Mar 18 '13 at 17:49
1

In a related question, I posted the following potential solutions:

def while_equal(seq, other):
    for this, that in zip(seq, other):
        if this != that:
            return
        yield this

def match(seq, other):
    return sum(1 for _ in while_equal(seq, other))

and

def match_loop(seq, other):
    count = 0
    for this, that in zip(seq, other):
        if this != that:
            return count
        count += 1
    return count

These versions are both faster than the other given solutions (the second being the fastest), and, I would argue, more readable.

Community
  • 1
  • 1
Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
0

Edit: as jamylak pointed out, mine solution is wrong. I'll keep it here so everyone who wants to answer this question will see the whole problem, not just first two cases.

Yet another solution which doesn't require itertools, though it'll be not as efficient as jamylak's solution.

def compareLists(list1, list2):
    return sum(map(lambda (x,y): 1 if x == y else 0, zip(list1, list2)))
Community
  • 1
  • 1
aga
  • 27,954
  • 13
  • 86
  • 121