How to reduce lines with list comprehensions in Python? - python

I have some syntax :
l_one = [ x for x in someList ] # list with duplicates
l = []
l_two = [ l.append( y ) for y in l_one if y not in l ] # duplicates removed
Both l and l_two are the same lists without duplicates. Is there way to reduce lines and maybe have oneliner?
EDIT :
Correction - l_two are the "Noned" list.

Actually, they aren't the same. .append() returns None because it modifies the list in place, so l_two is a list with a bunch of Nones. However, l will be the list with no dupes.
If you want to remove duplicates from a list, you can make it into a set:
l_two = list(set(l_one))
Note that this will remove order.
Try using a for-loop instead of a list comprehension if you want to use unhashable types:
l_one = [x for x in someList]
l_two = []
for i in l_one:
if i not in l_two:
l_two.append(i)
Or:
from itertools import groupby
l_two = [key for key, value in groupby(l_one)]

IF I'm understanding correctly, you're starting with a list called someList which may have duplicates, and you want to end up with the same list but with duplicates removed?
You could start by removing your first line of code, which just duplicates someList into a new (but identical) list called l_one:
>>> someList = [ 3,1,4,1,5,9,2,7 ]
>>> l = []
>>> [ l.append(y) for y in someList if y not in l]
[None, None, None, None, None, None, None]
>>> print l
[3, 1, 4, 5, 9, 2, 7]
>>>
This works even if the elements of someList are themselves lists:
>>> l = []
>>> someList = [[1,2],[2,1],[1,2],[3,4]]
>>> l = []
>>> [ l.append(y) for y in someList if y not in l]
[None, None, None]
>>> print l
[[1, 2], [2, 1], [3, 4]]
>>>

Related

flat 2d to 1d array

I have a list with a list inside.
Can you please help me - how to change the list of lists to list?
I tried with nd.array reshape(), flatten(), and ravel(), but no luck
Input:
['Test', [1, 2]]
Expected result:
['Test', 1, 2]
This problem is known as flattening an irregular list. There are a few ways you can do this -
Using list comprehension
l = ['Test', [1, 2]]
regular_list = [i if type(i)==list else [i] for i in l]
flatten_list = [i for sublist in regular_list for i in sublist]
flatten_list
['Test', 1, 2]
Using nested for loops
out = []
for i in l:
if type(i)==list:
for j in i:
out.append(j)
else:
out.append(i)
print(out)
['Test', 1, 2]
There are multiple answers, depending on context and preference:
For python lists:
flattened_list = [element for sublist in input_list for element in sublist]
# or:
import itertools
flattened_list = itertools.chain(*input_list)
Or, if you are using numpy.
flattened_list = list(original_array.flat)
# or, if you need it as a numpy array:
flattened_array = original_array.flatten()
You can try this:
li = ['Test', [1, 2]]
merged = []
for x in li:
if not isinstance(x, list):
merged.append(x)
else:
merged.extend(x)
print(merged)
Output: ['Test', 1, 2]

How to reassign an element of a list that is in another list as variable?

I'm trying to reassign an element in a list stored in a variable which is stored/called by another list, but I don't know how. Here are my lists:
list1 = [1,2,3]
list2 = [4,5,6]
listOfLists = [list1, list2]
So for example I want to change the value of the third element of the first list, I tried this but it doesn't work:
listOfLists[0][2]
I heard that you need to "travel all the list" with for - How it would be with this way?.
You need to use the = operator to assign a new value.
>>> list1 = [1,2,3]
>>> list2 = [4,5,6]
>>>
>>> listOfLists = [list1, list2]
>>> listOfLists[0][2] = 42
>>> listOfLists
[[1, 2, 42], [4, 5, 6]]
Note that the third element of the first list is now 42.

Python List Comprehension is not returning a new List

I am surprised by the behavior of List Comprehension on a list of lists. I would expect List comprehension to return a new list to me ALWAYS. For example:
>>> L = [1,2,3,4,5,6]
>>> M = [ x * 2 for x in L]
>>> L
>>> [1,2,3,4,5,6]
>>> M
>>> [2,4,6,8,10,12]
So L is not changed.
However,
>>> L = [[1], [2], [3]]
>>> M = [x.append(100) for x in L]
>>> M
>>> [None, None, None]
>>> L
>>> [[1,100], [2,100], [3,100]]
Now L is changed and list comprehension does not return a new List.
I am expecting a new List by the list comprehension. Any explanation would help me to understand this behavior of list comprehension
x * 2 is an expression which evaluates to a result and its result will be stored in the list M.
x.append(100) on the other hand applies function append() on the object x, which is an element of list L and returns None.
It is the same, why you do y = x * 2, but not y = x.append(100).
x.append(100)
Return nothing(None), this why you have only None's inside M.
You are appending to x, is an element in L, that is why L changes. If you want a new list do not mutate a older, create a new one.
You don't specify a result you expect, but I believe this what your looking for:
>>> L = [[1], [2], [3]]
>>> M = [[*x, 100] for x in L]
>>> L
[[1], [2], [3]]
>>> M
[[1, 100], [2, 100], [3, 100]]

manipulating lists to find different variables

The following is the first line from my list l:
[0.0, 753.128, 990.43, 686.832, 366.922, -93.454, 1.0]
This is the result of:
print l[0]
I want to take all the first element from all such *lines of my list and assign them to another list. How can I do it in python?
Using a list comprehension:
lists = [[1,2,3], [4,5,6]]
[ l[0] for l in lists ]
That would do it. Nicer is to use map: you map a list of lists to a list of their heads:
map( lambda l: l[0], lists )
If performance is important, you may want to create an iterator over the heads of your lists:
heads = itertools.imap( lambda l: l[0], enumerate(lists))
for head in heads:
print head
Basic list comprehension:
another_list = [sublist[0] for sublist in l]
Try this:
a = [[1,2,3], ['a','b','c'], [True, False]]
first_elements = [e[0] for e in a]
print first_elements
>>> [1, 'a', True]
Something like this?
>>> a = [1, 2, 3, 4]
>>> b = [5,6,7,8]
>>> ab = [a, b]
>>> map (lambda x : x[0], ab)
[1, 5]
newlist=[]
for l in lst:
newlist.append(l[0])

Remove evens from a list with del function

I'm not allowed to use the .remove() function to delete even numbers in a list and the specs say: You will be modifying the original list, so its id() must not change.This is what I have:
def remove_evens(xs):
for i in range(len(xs)):
for x in xs:
if x%2==0:
del xs[i]
return xs
If for instance I test the function and I input xs=[1,2,3,4,5] it returns [3,5]. I don't know why the 1 doesn't return
That's because you're iterating over the list and modifying it at the same time. This means the index i isn't always correct because you've just removed an element from the list. This leads to skipping elements and that's why the 1 isn't in there.
You can do:
def remove_evens(xs):
return [x for x in xs if x % 2 != 0]
This uses a list comprehension to create a list without the even numbers. If you need to modify the existing list you can do:
def remove_evens(xs):
to_remove = []
for i, x in enumerate(xs):
if x % 2 == 0:
to_remove.append(i)
for j in to_remove:
del xs[j]
return xs
This creates a list to_remove which keeps track of the positions of the elements that need to be removed.
Maybe something like this will work for you.
>>> xs = [1,5,123,6,2,34]
>>> id(xs)
35519496L
>>> lastidx = len(xs) - 1
>>> for i, x in enumerate(reversed(xs)):
... if x%2==0:
... del xs[lastidx-i]
...
>>> xs
[1, 5, 123]
>>> id(xs)
35519496L
It's linear time because it iterates over the list only once. When you iterate over a list backwards, you can freely delete elements without modifying the indexes of future elements that you haven't looped over yet. Also the id of the list does not change with this method, as you can see. :)
Here is another way to do the same thing with only range/xrange and len.
>>> xs = [1,5,123,6,2,34]
>>> for i in range(len(xs)-1,-1,-1):
... if xs[i]%2==0:
... del xs[i]
...
>>> xs
[1, 5, 123]
Both ways do the same thing so whichever way you decide to use is a matter of preference/personal style.
It’s a bad idea to delete items from a list as you are iterating over the list.
Here’s a few ways in which you can achieve your goal:
>>> def deleteEvens(L):
... dels = []
... for i,x in enumerate(L):
... if not x%2:
... dels.append(i)
... for d in dels[::-1]:
... L.pop(d)
...
>>> L
[1, 2, 3, 4, 5]
>>> deleteEvens(L)
>>> L
[1, 3, 5]
OR
>>> L = [1,2,3,4,5]
>>> odds = [i for i in L if i%2]
>>> odds
[1, 3, 5]
OR
>>> def delEvens(L):
... dels = []
... for i,x in enumerate(L):
... if not x%2:
... dels.append(i)
... for d in dels[::-1]:
... del L[d]
...
>>> L = [1,2,3,4,5]
>>> delEvens(L)
>>> L
[1, 3, 5]

Categories