Python: compare list and list of tuples
I have a list as shown below:
z = [('Anna Smith', 'IN1'), ('John', 'IN2'), ('Matt Andrew', 'IN3'), ('Smith', 'IN4')]
And one more list:
c = ['Anna Smith', 'John', 'Anna', 'Smith']
I need the following output:
o = ['Anna Smith|IN1', 'John|IN2', 'Smith|IN4']
I have tried the below code:
for s, s_inc in z:
for word in c:
if word.lower() in s.lower():
o.append("%s|%s"%(word, s_inc))
But the above gives me the output:
o = ['Anna Smith|IN1', 'Anna|IN1', 'Smith|IN1', 'John|IN2', 'Smith|IN4']
How do I get what I want?
source to share
List comprehension is an elegant technique for this type of filtering / list problems.
Understanding has three parts:
-First result is plotted in + '|' + b
... Second, a and b are assigned to the first and second element in every 2-tuple in the list z
... Third, we filter the condition that a must be a member of the list c
print [a+'|'+b for a,b in z if a in c]
# Prints ['Anna Smith|IN1', 'John|IN2', 'Smith|IN4']
source to share
From your examples, it sounds like you are looking for an exact match, so use ==
instead in
:
for s, s_inc in z:
for word in c:
if word == s:
o.append("%s|%s"%(word, s_inc))
Or, in short, as a single list comprehension:
o = ["%s|%s"%(s, s_inc) for s, s_inc in z if s in c]
After that o
there is['Anna Smith|IN1', 'John|IN2', 'Smith|IN4']
source to share
I would make c
a quick test suite with constant time:
c_set = {w.lower() for w in c}
I am antialiasing the words so that it is easy to check membership in a case insensitive manner.
Then just use:
for s, s_inc in z:
if s.lower() in c_set:
o.append('|'.join([s, s_inc]))
or even:
o = ['|'.join([s, s_inc]) for s, s_inc in z if s.lower() in c_set]
to create an entire combo box.
Demo:
>>> z = [('Anna Smith', 'IN1'), ('John', 'IN2'), ('Matt Andrew', 'IN3'), ('Smith', 'IN4')]
>>> c = ['Anna Smith', 'John', 'Anna', 'Smith']
>>> c_set = {w.lower() for w in c}
>>> ['|'.join([s, s_inc]) for s, s_inc in z if s.lower() in c_set]
['Anna Smith|IN1', 'John|IN2', 'Smith|IN4']
source to share