List comprehension flat list? - python-3.x

I have the following toy function:
def foo(a):
return [a+5]
And I am running the following code:
my_lst = [foo(x) for x in range(10) if x%2 == 0]
Getting:
[[5], [7], [9], [11], [13]]
But need:
[5,7,9,11,13]
But I want to get a plain list, not a list of lists.
How can I do it without itertools.chain.from_iterable(my_lst) but with list comprehension?
What is the best practice? itertools or list comprehension in this case?
Please advice.
I have tried:
[j[0] for j in [foo(x) for x in range(10) if x%2 == 0]]
Should I do it like this or there is a better way?

With list comprehension, it's done using two for loops:
my_lst = [subx for x in range(10) if x%2 == 0 for subx in foo(x)]
Also if you have a list of lists of one elements, you can "transpose" after the fact the list using zip:
bad_lst = [foo(x) for x in range(10) if x%2 == 0]
[my_lst] = zip(*bad_lst)
Or you can "transpose" using a list comprehension combined with list unpacking as well if you truly want a list as output and not a tuple:
bad_lst = [foo(x) for x in range(10) if x%2 == 0]
my_lst = [x for [x] in bad_lst]

alternatively to Laernes answer, you can also use itertools as :
list(itertools.chain(*[foo(x) for x in range(10) if x%2 == 0]))
or
list(itertools.chain.from_iterable([foo(x) for x in range(10) if x%2 == 0]))
More options here:

Your function should return a number, not a list:
def foo(a):
return a+5

Related

How to merge multiple tuples or lists in to dictionary using loops?

Here is my code to merge all tuple in to dictionary,
x = (1,2,3)
y = ('car',"truck","plane")
z=("merc","scania","boeing")
products={}
for i in x,y,z:
products[x[i]]= {y[i]:z[i]}
output:
error:
6 for i in x,y,z:
----> 7 products[x[i]]= {y[i]:z[i]}
8
9 print(products)
TypeError: tuple indices must be integers or slices, not a tuple
Now if i use indexing method inside loop for identifying positions like below code,
for i in x,y,z:
products[x[0]]= {y[0]:z[0]}
print(products)
out:
{1: {'car': 'merc'}}
here, I could only create what I need but only for a specified index how do create a complete dictionary using multiple lists/tuples??
is it also possible to use Zip & map functions?
Use zip to iterate over your separate iterables/tuples in parallel
list(zip(x, y, z)) # [(1, 'car', 'merc'), (2, 'truck', 'scania'), (3, 'plane', 'boeing')]
x = (1, 2, 3)
y = ("car", "truck", "plane")
z = ("merc", "scania", "boeing")
products = {i: {k: v} for i, k, v in zip(x, y, z)}
print(products) # {1: {'car': 'merc'}, 2: {'truck': 'scania'}, 3: {'plane': 'boeing'}}
You should use integer as indices.
x = (1,2,3)
y = ('car',"truck","plane")
z=("merc","scania","boeing")
products={}
for i in range(len(x)):
products[x[i]]= {y[i]:z[i]}
This should solve your problem
To add for above answer, I'm posting a solution using map,
x = (1,2,3)
y = ('car',"truck","plane")
z=("merc","scania","boeing")
products=dict(map(lambda x,y,z:(x,{y:z}),x,y,z))
print(products)

Find the index location of an element in a Numpy array

If I have:
x = np.array(([1,4], [2,5], [2,6], [3,4], [3,6], [3,7], [4,3], [4,5], [5,2]))
for item in range(3):
choice = random.choice(x)
How can I get the index number of the random choice taken from the array?
I tried:
indexNum = np.where(x == choice)
print(indexNum[0])
But it didn't work.
I want the output, for example, to be something like:
chosenIndices = [1 5 8]
Another possibility is using np.where and np.intersect1d. Here random choice without repetition.
x = np.array(([1,4], [2,5], [2,6], [3,4], [3,6], [3,7], [4,3], [4,5], [5,2]))
res=[]
cont = 0
while cont<3:
choice = random.choice(x)
ind = np.intersect1d(np.where(choice[0]==x[:,0]),np.where(choice[1]==x[:,1]))[0]
if ind not in res:
res.append(ind)
cont+=1
print (res)
# Output [8, 1, 5]
You can achieve this by converting the numpy array to list of tuples and then apply the index function.
This would work:
import random
import numpy as np
chosenIndices = []
x = np.array(([1,4], [2,5], [2,6], [3,4], [3,6], [3,7], [4,3], [4,5], [5,2]))
x = x.T
x = list(zip(x[0],x[1]))
item = 0
while len(chosenIndices)!=3:
choice = random.choice(x)
indexNum = x.index(choice)
if indexNum in chosenIndices: # if index already exist, then it will rerun that particular iteration again.
item-=1
else:
chosenIndices.append(indexNum)
print(chosenIndices) # Thus all different results.
Output:
[1, 3, 2]

How to delete certain element(s) from an array?

I have a 2d array, how can I delete certain element(s) from it?
x = [[2,3,4,5,2],[5,3,6,7,9,2],[34,5,7],[2,46,7,4,36]]
for i in range(len(x)):
for j in range(len(x[i])):
if x[i][j] == 2:
del x[i][j]
This will destroy the array and returns error "list index out of range".
you can use pop on the list item. For example -
>>> array = [[1,2,3,4], [6,7,8,9]]
>>> array [1].pop(3)
>>> array
[[1, 2, 3, 4], [6, 7, 8]]
I think this can solve your problem.
x = [[2,3,4,5,2],[5,3,6,7,9,2],[34,5,7],[2,46,7,4,36]]
for i in range(len(x)):
for j in range(len(x[i])):
if j<len(x[i]):
if x[i][j] == 2:
del x[i][j]
I have tested it locally and working as expected.Hope it will help.
Mutating a list while iterating over it is always a bad idea. Just make a new list and add everything except those items you want to exclude. Such as:
x = [[2,3,4,5,2],[5,3,6,7,9,2],[34,5,7],[2,46,7,4,36]]
new_array = []
temp = []
delete_val = 2
for list_ in x:
for element in list_:
if element != delete_val:
temp.append(element)
new_array.append(temp)
temp = []
x = new_array
print(x)
Edit: made it a little more pythonic by omitting list indices.
I think this is more readable at the cost of temporarily more memory usage (making a new list) compared to the solution that Sai prateek has offered.

convert string elements in list as integers in python

I have a list named newlist
newlist=[['24,4,17,46,0,43'], ['11,43,17'], ['33,17,43,4'], ['74,21'],['21,43,43,74,68,21']]
I need to convert each list element as integers.i.e.
newlist=[[24,4,17,46,0,43], [11,43,17], [33,17,43,4], [74,21], [21,43,43,74,68,21]].
Can anyone help me please.
Python 3:
newlist=[['24,4,17,46,0,43'], ['11,43,17'], ['33,17,43,4'], ['74,21'],['21,43,43,74,68,21']]
mylist = list(map(lambda x : list(map(int, x[0].split(','))) , newlist))
print(mylist)
Python 2:
newlist=[['24,4,17,46,0,43'], ['11,43,17'], ['33,17,43,4'], ['74,21'],['21,43,43,74,68,21']]
mylist = map(lambda x : map(int, x[0].split(',')) , newlist)
print mylist

Python- converting to float using map()

If I have a list like the one given below, and want to convert the given integers to float, is there a way I can do it with map()?
my_list=[['Hello', 1 , 3],['Hi', 4 , 6]]
It's ugly, but yeah, it can be done:
my_list=[['Hello', 1 , 3],['Hi', 4 , 6]]
print(list(map(lambda lst: list(map(lambda x: float(x) if type(x) == int else x, lst)), my_list)))
# Output: [['Hello', 1.0, 3.0], ['Hi', 4.0, 6.0]]
EDIT
I personally prefer list comprehension in most cases as opposed to map/lambda, especially here where all the conversions to lists are annoying:
print([
[float(x) if type(x) == int else x for x in lst]
for lst in my_list
])
EDIT 2
And finally, an in-place solution that uses good old for loops:
for lst in my_list:
for i, item in enumerate(lst):
if type(item) == int:
lst[i] = float(item)
print(my_list)
If you are going to use map, you can increase readability by using it with previously defined functions. First make a function which converts an object to a float if possible, and leaves it alone if not:
def toFloat(x):
try:
return float(x)
except:
return x
Then you can map this across a list like:
def listToFloats(items):
return list(map(toFloat,items))
And then map this last function across a list of lists:
def listsToFloats(lists):
return list(map(listToFloats,lists))
For example:
>>> my_list=[['Hello', 1 , 3],['Hi', 4 , 6]]
>>> listsToFloats(my_list)
[['Hello', 1.0, 3.0], ['Hi', 4.0, 6.0]]

Resources