How to compare the list elements in Python - python

Here i am having two lists :
list1 = ['2C535EB58F19B58' , '7B89D9071EB531B143594FF909BAC846' , '0509']
list2 = ['1641AB0C9C5B8867' , '0098968C' , '509']
I need to compare the elements inside list2 with list1 elements.
I want the output to be , after comparing :
509
since 509 is present in 0509.
How can i achieve so ? Does regex can help me in this ?

Try this:
Here we are checking whether element in list2 is a substring of an element in list1.
list1 = ['2C535EB58F19B58' , '7B89D9071EB531B143594FF909BAC846' , '0509']
list2 = ['1641AB0C9C5B8867' , '0098968C' , '509']
for i, j in zip(list1, list2):
if j in i:
print(j)
One-liner which will append to a list:
print( [j for i, j in zip(list1, list2) if j in i])
There could be more simple and better answers. If it helps, you can opt it.

You can do something like this:
common_elements = []
for x in list1:
for y in list2:
if y in x:
common_elements.append(y)
common_elements will contain the elements you need.

As already proposed by BearBrown in a comment, there is an easy way to achieve your goal. There is no reason to think about regular expressions at all (the in-operator is powerful enough).
[x for x in list2 if any(y for y in list1 if x in y)]
Here you are looking for each string x in list2 if it is a substring of any string y in list1 and finally save each matching substring x in a new list.

for x in list2:
for y in list1:
if x in y:
print x #or whatever
nested for-loops, I think this is a simple way, but I'm sure there is a better one

You can simply use in operation in python to check whether one string is in another string.
The easiest way to solve your problem would be
[y for y in list2 if any(y in x for x in list1)]

Related

filter a list based on values in another list

list1 = ['a','b','c','d']
list2 = [1,0,1,0]
Given two lists like the above, I would like to obtain a third list whose values are ['a','c']
In other words, I'd like the target list to be the values from list1 where the corresponding element in list2 is 1.
As noted in the comments:
[i for i, j in zip(list1, list2) if j] would work.
Alternatively, if you were looking for something not so advanced:
list3 = []
for i in range(len(list1)):
if list2[i] == 1:
list3.append(list1[i])
Use enumerate function on second list to include index, which can be used for the first list.
[list1[i] for i, item in enumerate(list2) if item]
Generators can be nice if you have very long lists:
def filterfunc(a, b, keyvalue=1):
return (x for i, x in enumerate(a) if b[i] == keyvalue)
To get the whole sequence:
list(filterfunc(a, b))

Selection elements of a list based on another 'True'/'False' list

I have two lists of the same length.
The first one contains strings. The second one - strings that can be either 'True' or 'False'.
If the nth element of the second list is 'True', I want to append the nth element of the first list to another list.
So if I have:
List1:
('sth1','sth2','sth3','sth4')
List2:
('True','False','True','False')
The outcome should be List3:
('sth1','sth3').
How can I intersect two list in that way?
Use zip:
result = [x for x, y in zip(xs, ys) if y == 'True']
Example:
xs = ('sth1','sth2','sth3','sth4')
ys = ('True','False','True','False')
result = [x for x, y in zip(xs, ys) if y == 'True']
result
['sth1', 'sth3']
Or use numpy:
import numpy as np
filtered = np.array(List1)[np.array(List2)]
Btw this only works if the elements inside List2 are True/False, not if they are "True"/"False".
If you didn't know about zip :
l1 = ('sth1','sth2','sth3','sth4')
l2 = ('True','False','True','False')
l = [x for i,x in enumerate(l1) if l2[i]=='True']
print l
#=> ['sth1', 'sth3']
It would be shorter with a tuple of booleans :
l1 = ('sth1','sth2','sth3','sth4')
l2 = (True,False,True,False)
l = [x for i,x in enumerate(l1) if l2[i]]
print l
Simplest way is to use itertools.compress method as follows.
import itertools
list1 = ('sth1','sth2','sth3','sth4')
list2 = ('True','False','True','False')
list2 = map(lambda x: x == 'True', list2)
result = list(itertools.compress(list1, list2))
compress method returns an iterator, so you that is why you need to wrap the iterator object in list
I hope it helps.

Counting elements in a list with given property values

I'm using Python 2.7. I have a list of objects that each include a property called vote that can have values of either yes or no, and I want to count the number of yes and no votes. One way to do this is:
list = [ {vote:'yes'}, {vote:'no'}, {vote:'yes'} ] #...
numYesVotes = len([x for x in list if x.vote=='yes'])
numNoVotes = len([x for x in list if x.vote=='no'])
but it seems horribly wasteful/inefficient to me to build these lists only to get their lengths and
First question: Am I right about that? Wouldn't it a good bit more efficient to simply loop through the list once and increment counter variables? i.e:
numYesVotes = numNoVotes = 0;
for x in list:
if x.vote == 'yes':
numYesVotes++
else:
numNoVotes++
or is there something about list comprehensions that would make them more efficient here?
Second question: I'm just learning to use lambdas, and I have a feeling this is a perfect use case for one - but I can't quite figure out how to use one here how might I do that?
See Counter
Counter(x.vote for x in mylst)
Edit:
Example:
yn = Counter("yes" if x%2 else "no" for x in range(10))
print(yn["yes"],yn["no"])
Note that it is faster to do:
sum(1 for x in L if x.vote=='yes')
Than:
len([x for x in L if x.vote=='yes'])
As no list has to be created.
The lambda form;
t =lambda lst: len([ v for x in lst for k,v in x.items() if v=='yes'])
#print (t(mylst))
mylst is the list that you want to check how much yes or no in that. Use key-dict methods.
Demo;
mylst = [ {"vote":'yes'}, {"vote":'no'}, {"vote":'yes'} ]
t =lambda lst: len([ v for x in lst for k,v in x.items() if v=='yes'])
print (t(mylst))
>>>
2
>>>

Python: more readable list comprehension

I am new to Python. I have the following code which is a part of a string algorithm that i'm currently developing.
>>> newlist=[]
>>> i =0
>>> for x in range(len(list1)):
new_item = [y for y in list1[i] if y not in list2[i]]
newlist.append(new_item)
i=i+1
>>> print newlist
I like to do this using list comprehension as I've read it is performance optimized. Can somebody suggest me a method.
Thank you.
[Edit]
example:
list1= [[['pat'],['cut'],['rat']], [['sat','pat'],['cut','pat']],[['instructor','plb','error0992'],['instruction','address','00x0993'],['data','address','017x112']]
list2= [[['pat'], ['cut'], ['rat']], [['sat', 'pat']], [['instructor', 'plb', 'error0992'], ['instruction', 'address', '00x0993']]]
So the new list,
newlist= [[], [['cut', 'pat']], [['data', 'address', '017x112']]]
If you just want all elements that are in one list and not in another, I would suggest looking into python sets. They don't allow for duplicates, but the performance and readability benefits are large.
You would implement this like so:
newlist = list(set(list1).difference(set(list2)))
If you want to apply this in place of your current solutions, you should do something along the lines of what Dominic suggested (slightly edited for readability):
[list(set(a)-set(b)) for a, b in zip(list1, list2)]
If the order matters, or you have duplicates, then the single list comprehension you had above should do the trick, just wrap it as a lambda function to make it more readable:
single_item = lambda i: [y for y in list1[i] if y not in list2[i]]
newlist = [single_item(i) for i in enumerate(list1)]
This is a nested list comprehension that does the same thing as your code (albeit will not preserve the value of i).
newlist = [[y for y in list1[i] if y not in list2[i]] for i in range(len(list1))]
TL;DR: [[y for y in list1[i] if j not in list2[i]] for i in enumerate(list1)]
You should use enumerate instead of the range(len()) non-idiom. You may also want to consider making this a generator expression. Either with a concrete nested list:
([y for y in list1[i] if j not in list2[i]] for i in enumerate(list1))
or not
((y for y in list1[i] if j not in list2[i]) for i in enumerate(list1))

How to delete a dictionary from a list based on values from another dictionary in a list?

I've spent about 6 hours on this, so I feel justified in asking a question. :)
My problem
list1 = [
{extension: 1000, id: 1}
{extension: 1001, id: 1}
{extension: 1000, id: 2}
]
list2 = [
{Stationextension: 1000, id: 1, name: bob}
{Stationextension: 1001, id: 1, name: sal}
{Stationextension: 1000, id: 2, name: cindy}
]
My pseudo code is this.
Delete list2[d] (whole dictionary from list of dicts) where list1[d]['extension'] == list2[d]['Stationextension'] AND id == id.
List 1 is much smaller and has to stay unchanged relative to list 2 if that matters.
Using Python3.3, I have something like
[x for x in list2 if (list1[x]['stationExtension'] == x.get('extension'))]
Thanks !
list2 = [x for x in list2 if {'extension': x['Stationextension'], 'id': x['id']} not in list1]
or, if you know that the lengths and indexes will match:
list2 = [y for x,y in itertools.izip(list1, list2) if x['extension'] == y['StationExtension'] and x['id'] == y['id']]
The right way to do this is to use the right data structures for the job. Instead of figuring out how to search a list based on a key, use a dict with that key. For example:
dict1 = {x['extension']: x for x in list1}
Now, you can just write this:
[x for x in list2 if x['stationExtension'] in dict1}
Elsewhere in your question, it seems like you wanted to use the extension and the id, not just the extension, as a key. But that's just as easy; you can use a tuple:
dict1 = {(x['extension'], x['id']): x for x in list1}
[x for x in list2 if (x['stationExtension'], x['id']) in dict1}
If you want to know why your code doesn't work… let's look at it:
[x for x in list2 if (list1[x]['stationExtension'] == x.get('extension'))]
list1[x] is trying to use the dict as an index, which doesn't mean anything. What you really want to say is "if, for any element of list1, element['stationExtension'] == x.get('extension')". And you can translate that almost directly to Python:
[x for x in list2
if any(element['stationExtension'] == x.get('extension')
for element in list1)]
And of course to add the and element['id'] == x['id'] onto the end of the condition.
But again, the dict is a better solution. Besides being a whole lot simpler to read and write, it's also more efficient. Searching for any matches in a list requires checking each element in the list; searching for any matches in a dict just requires hashing the key and looking it up in a hash table. So, this way takes O(NM) time (where N is the length of list1, and M is the length of list2), while the dict only takes O(M) time.
Assuming that you want to delete items from list2 with the same value in "Stationextention" on list2 and "extention" on list 1 -
You better first create a set with all values to delete - that will avoid a linear search at each time you want to check if an entry will stay:
indexes = set(item["extention"] for item in list1)
And - one thing that happens is that you usually can't iterate over a list and delete items from it while at it:
new_list2 = []
for item in list2:
if item["Stationextention"] not in indexes:
new_list2.append(item)
list2 = new_list2
Python 2.7:
removelist=[]
for i,x in enumerate(list2):
if x['Stationextension'] == list1[i]['extension'] and x['id'] == list1[i]['id']:
removelist+=[i]
And once you've decided what to delete:
for x in removelist:
del list1[x]

Categories