Python: more readable list comprehension - python

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))

Related

How to increase list in python [duplicate]

This question already has answers here:
How to add an integer to each element in a list?
(12 answers)
Closed last month.
I would like to get such a result [2,4,5,6,7], how can do that? Now i get this: [7]
list1 = [1,3,4,5,6]
for i in range(len(list1)):
l = []
# list1[i] = list1[i] + 1
s = list1[i] + 1
l.append(s)
print(l)
you can use list comprehension
list1 = [1,3,4,5,6]
newlist = [x+1 for x in list1]
print(newlist)
If you want to use a loop, you need to put l = [] ahead of it - otherwise you're reintializing it as an empty list at each loop iteration,
list1 = [1,3,4,5,6]
l = []
for el in list1:
l.append(el + 1)
print(l)
Notice that this code directly loops through elements of list1. This is a preferred way for lists and any other iterables. I recommend you use it whenever practical/possible.
As an alternative to list comprehensions and loops, you can also use a map with a lambda,
list1 = [1,3,4,5,6]
new_list = list(map(lambda x: x+1, list1))
print(new_list)
Note, however, that in most situations, including this one, list comprehension is a better choice. For reasons and details, look up this post.
This will work:
list1 = [1,3,4,5,6]
for i in range(len(list1)):
list1[i]+=1
print(list1)

How delete a element of a list and save the original index of deleted element?

I want delete some elements of one list equal to a value:
I can do it :
List =[1,2,3.....]
List = [x for x in List if x != 2]
How can i save the indexs of the deleted elements ?
I want to use this index to delete elements of another list.
Simplest solution is to make a list of indices to keep, then use that to strip the elements from both of your lists. itertools provides a handy compress utility to apply the indices to keep quickly:
from itertools import compress
tokeep = [x != 2 for x in List]
List = list(compress(List, tokeep))
otherlist = list(compress(otherlist, tokeep))
Alternatively (and frankly more clearly) you can just use one loop to strip both inputs; listcomps are fun, but sometimes they're not the way to go.
newlist = []
newotherlist = []
for x, y in zip(List, otherlist):
if x != 2:
newlist.append(x)
newotherlist.append(y)
which gets the same effect in a single pass. Even if it does feel less overtly clever, it's very clear, which is a good thing; brevity for the sake of brevity that creates complexity is not a win.
And now, to contradict that last paragraph, the amusingly overtly clever and brief solution to one-line this:
List, otherlist = map(list, zip(*[(x, y) for x, y in zip(List, otherlist) if x != 2]))
For the love of sanity, please don't actually use this, I just had to write it for funsies.
You can also leverage enumerate
for index, val in enumerate(List):
if val == value:
del List[index]
break
print(index)
Based on documentation
list_first = ['d', 'a']
list_second = ['x', 'z']
def remove_from_lists(element):
index_deleted = list_first.index(element)
list_first.remove(element)
list_second.pop(index_deleted)
remove_from_lists('d')

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))

How to compare the list elements in 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)]

How to read aloud Python List Comprehensions?

My question is about Python List Comprehension readability. When I come across code with complex/nested list comprehensions, I find that I have to re-read them several times in order to understand the intent.
Is there an intuitive way to read aloud list comprehensions? Seems like I should start "reading" from the middle, then read the if conditions (if any), and read the expression last.
Here's how I would read the follow line of code aloud, in order to understand it:
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
"For each element in List x, and each element in List y, if the two elements are not the same, create a list of tuples."
Two examples that I am struggling with:
How would you read the following List Comprehensions aloud?
From another question in Stack Overflow: [x for b in a for x in b]
Python docs has this example:
[[row[i] for row in matrix] for i in range(4)]
Any suggestions or pointers for ways to read aloud list comprehensions such that the intention becomes clearer is much appreciated.
I usually unfold it in my mind into a generating loop, so for example
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
is the list comprehension for the generator
for x in [1,2,3]:
for y in [3,1,4]:
if x != y:
yield (x, y)
Example #1
[x for b in a for x in b] is the comprehension for
for b in a:
for x in b:
yield x
Example result for a = [[1,2,3],[4,5,6]]: [1, 2, 3, 4, 5, 6]
Example #2
[[row[i] for row in matrix] for i in range(4)] (note the inner expression is another comprehension!):
for i in range(4):
yield [row[i] for row in matrix]
which is unfolded
for i in range(4):
l = []
for row in matrix:
l.append(row[i])
yield l
"Construct a list of X's based on Y's and Z's for which Q is true."

Categories