Not the most efficient one, but by far the most obvious way to do it is:
>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
{5}
if order is significant you can do it with list comprehensions like this:
>>> [i for i, j in zip(a, b) if i == j]
[5]
(only works for equal-sized lists, which order-significance implies).
Answer from SilentGhost on Stack OverflowNot the most efficient one, but by far the most obvious way to do it is:
>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
{5}
if order is significant you can do it with list comprehensions like this:
>>> [i for i, j in zip(a, b) if i == j]
[5]
(only works for equal-sized lists, which order-significance implies).
Use set.intersection(), it's fast and readable.
>>> set(a).intersection(b)
set([5])
Videos
Personally, I think dicts would suit your solution better, as you can access them via their keys (e.g. dict['km_driven']) which is less confusing than integer indices in a list.
This code works using lists:
# list1 = ('Name', 'Kilometers Driven')
list1 = [('Joe Doe', 500),('Jane Doe', 200)]
# list2 = ('Id','Name','Kilometers Walked','Total Events', optional='Kilometers Driven')
list2 = [(2,'Joe Doe',20,2),(3,'Frank Kelly',32,4)]
# Iterate through items of list1
for item1 in list1:
# Iterate through items of list2
for i in range(len(list2)):
# Match 'Name' field in list1 to 'Name' field in list2
if item1[0] == list2[i][1]:
# Add 'Kilometers Driven' to that list2 item
list2[i] = list2[i] + (item1[1], )
print(list2[0])
Output:
(2, 'Joe Doe', 20, 2, 500)
Given data lists: (list1 and list 2 are a list of tuples.)
list1 = [ ('John Doe', 500), ('Jane Doe', 200) ]
list2 = [ (2,'John Doe',20,2), (3,'Frank Kelly',32,4) ]
for i in list1:
name,km=i #unpacking tuple into name and km driven
for index,j in enumerate(list2): #iterate list2 with index
if name in j: # if name exists in element j of list2
two[index]=two[idx]+(km,) #add km driven to element j
The value of list2 after the for loop:
[(2, 'John Doe', 20, 2, 500), (3, 'Frank Kelly', 32, 4)]
I might do something like:
set1 = set((x.id,x.name,...) for x in list1)
difference = [ x for x in list2 if (x.id,x.name,...) not in set1 ]
where ... is additional (hashable) attibutes of the instance -- You need to include enough of them to make it unique.
This takes your O(N*M) algorithm and turns it into an O(max(N,M)) algorithm.
Just a thought...
class Foo(object):
def __init__(self, id, name):
self.id = id
self.name = name
def __repr__(self):
return '({},{})'.format(self.id, self.name)
list1 = [Foo(1,'a'),Foo(1,'b'),Foo(2,'b'),Foo(3,'c'),]
list2 = [Foo(1,'a'),Foo(2,'c'),Foo(2,'b'),Foo(4,'c'),]
So ordinarily this does not work:
print(set(list1)-set(list2))
# set([(1,b), (2,b), (3,c), (1,a)])
But you could teach Foo what it means for two instances to be equal:
def __hash__(self):
return hash((self.id, self.name))
def __eq__(self, other):
try:
return (self.id, self.name) == (other.id, other.name)
except AttributeError:
return NotImplemented
Foo.__hash__ = __hash__
Foo.__eq__ = __eq__
And now:
print(set(list1)-set(list2))
# set([(3,c), (1,b)])
Of course, it is more likely that you can define __hash__ and __eq__ on Foo at class-definition time, instead of needing to monkey-patch it later:
class Foo(object):
def __init__(self, id, name):
self.id = id
self.name = name
def __repr__(self):
return '({},{})'.format(self.id, self.name)
def __hash__(self):
return hash((self.id, self.name))
def __eq__(self, other):
try:
return (self.id, self.name) == (other.id, other.name)
except AttributeError:
return NotImplemented
And just to satisfy my own curiosity, here is a benchmark:
In [34]: list1 = [Foo(1,'a'),Foo(1,'b'),Foo(2,'b'),Foo(3,'c')]*10000
In [35]: list2 = [Foo(1,'a'),Foo(2,'c'),Foo(2,'b'),Foo(4,'c')]*10000
In [40]: %timeit set1 = set((x.id,x.name) for x in list1); [x for x in list2 if (x.id,x.name) not in set1 ]
100 loops, best of 3: 15.3 ms per loop
In [41]: %timeit set1 = set(list1); [x for x in list2 if x not in set1]
10 loops, best of 3: 33.2 ms per loop
So @mgilson's method is faster, though defining __hash__ and __eq__ in Foo leads to more readable code.
The problem with this is that, for each element in list A, you're checking all of the elements in list B. So, if the lengths of your lists are N and M, that's N*M comparisons.
If you make a set of the usernames from list B, then you can just use the in operator on it—which is not only simpler, it's instantaneous, instead of having to check all of the values one by one. So, you only need N lookups instead of N*M.
So:
b_names = {record.username for record in List_B}
for record_a in List_A:
if record_a.username in b_names:
print "Duplicate username: {0}".format(record_a.username)
Or, even simpler, use set intersection:
a_names = {record.username for record in List_A}
b_names = {record.username for record in List_B}
for name in a_names & b_names:
print "Duplicate username: {0}".format(name)
And really, you don't need both of them to be sets, you can make one a set and the other just an iterator, using a generator expression:
a_names = {record.username for record in List_A}
b_names = (record.username for record in List_B)
for name in a_names.intersection(b_names):
print "Duplicate username: {0}".format(name)
One of these may be a little faster than the others, but they'll all be in the same ballpark—and, more importantly, they're all linear instead of quadratic. So, I'd suggest using whichever one makes the most sense to you.
If you just need to know whether there are duplicates rather than get a list of them, or just need to get one of the duplicates arbitrarily rather than all of them, you can speed it up by "short-circuiting" early—e.g., adding a break after the print in the first one, or using isdisjoint instead of intersection in the last one.
You could try something like:
for rec_a, rec_b in zip(List_A, List_B):
if rec_a == rec_b:
print "Duplicate username: {0}".format(rec_a.username)
Mmm, like this?
if list1 == list2: # compare lists for equality
doStuff() # if lists are equal, do stuff after that
Of course, you need to clarify what do you mean by "if lists values match". The above will check to see if both lists have the same elements, in the same position - that is, if they're equal.
EDIT:
The question is not clear, let's see some possible interpretations. To check if all elements in list1 are also in list2 do this:
if all(x in list2 for x in list1):
doStuff()
Or to do something with each element in list1 that also belongs in list2, do this:
for e in set(list1) & set(list2):
doStuff(e)
Use any():
>>> L1 = [1,6]
>>> L2 = [1]
>>> any(i in L1 for i in L2)
True
Pretty much, it loops through each item in L2 and if any item in L2 is in L1, then it will return True.
If you want to see whether each item is in the other list, and print which ones are and which ones aren't:
>>> for i in L2:
... if i in L1:
... print i, "is in L1"
... else:
... doStuff(i)