compactly generate list of list python - python

I have to create a list of lists (each inner list has n fixed elements). Right now, for n=3 I am doing this:
my_list = []
for x in range(min_inner max_inner + 1):
for y in range(min_outer, max_outer + 1):
for z in range(fixed_param):
my_list.append([x, y, z])
When I tried list comprehension, something like:
[[x,y,z] for x in range(1,4), y in range(1,4), z in range (4)]
I get a name error
NameError: name 'z' is not defined
Is there a list comprehension way of doing that? Considering that n can be any number (though not necessarily arbitrarily large)

You need to loop over your range objects inside the list comprehension too.
[[x,y,z] for x in range(1,4) for y in range(1,4) for z in range (4)]
Also as a more concise way you could use itertools.product() to achieve the same result:
from itertools import product
list(product(range(1,4),range(1,4),range(4)))
Note that itertools.product() returns an iterator object which is pretty more optimized (in terms of memory usage) than list comprehension which returns a list. And if you just want to iterate over the result you don't need to convert the result to list. Otherwise the list comprehension will performs faster.

Related

Inserting the element-wise mean of nested list into the same list

Suppose there is a list of nested lists of floats
L = [[a,b,c],[e,f,g],[h,i,j]]
What kind of function can I define to iterate through the list once and insert the mean of elements of every consecutive list into the same list? I.e. I want to get
L1 = [[a,b,c],[(a+e)/2,(b+f)/2,(c+g)/2],[e,f,g],[(e+h)/2,(f+i)/2,(g+j)/2],[h,i,j]]
I know the function to get the element wise mean of two lists:
from operator import add
new_list = list(map(add,list1,list2))
J = [j/2 for j in new_list]
However inserting this list of mean values back into the same list while maintaining the proper index iteration through the old list proved challenging.
There are two cases:
You don't care if the resulting list is the same list:
new_list = []
for i in range(len(L)-1):
new_list.append(L[i])
new_list.append(list(map(lambda x: sum(x)/len(x), zip(L[i],L[i+1]))))
new_list.append(L[-1])
You want the changes to be done in-place:
i=0
while i < len(L)-1:
new_elem = list(map(lambda x: sum(x)/len(x), zip(L[i],L[i+1])))
L.insert(i+1, new_elem)
i += 2
EDIT: If you're using python 3.4 or above, instead of lambda x: sum(x)/len(x) you can use mean(x) (from the package statistics).

How to iterate a zip list and print each index of it after joining to lists of the same size?

Given the variables:
X = ['a', 'b', 'c']
Y = [1, 2, 3]
complete the following statement:
[print(pair) for pair in ...]
so as to print to the screen pairs of elements from X and Y which occupy the same position in the index.
I know I can make a join X and Y and make a list using list(zip(X,Y)) but the adding that in the statement gives an empty list.
I can't solve this problem using the form required any help?
thanks!
Not really clear what you're trying to achieve. If you need to print pairs, zip works, i.e.
for pair in zip(X, Y):
print(pair)
[print(pair) for pair in ...] is list comprehension, this is made to create lists, not to print data:
pairs_list = [pair for pair in zip(X, Y)] # don't do this
which is simply pairs_list = list(zip(X, Y)). Does this make sense to you?
Using list comprehensions to leverage a sideeffect (like printing something) is frowned upon. If you dont need a list, don't build one.
[print(pair) for pair in zip(X,Y)] # no need to list(zip(...))
will result in lots on None ... because the return value of print() is None.
Use a simple loop:
for p in zip(X,Y):
print(p)

Removing duplicates from a list of tuples in python

I have a list of tuples, and I want to remove duplicate tuples. Something like this.
x = [['aaron','jeng'],['sdf','wqd'],['aaron','jeng']]
I want the output something like this :
y = [['aaron','jeng'],['sdf','wqd']]
How can I do that in an easy way? I can write code to do that, but is there any inbuilt function for this?
Edit 1 : As everyone has suggested, I'm sorry to call them tuples. I meant a list of lists. Thank You.
Your x value does not contain a list of tuples, but a list of lists. If it did contain a list of tuples:
x = [('aaron','jeng'),('sdf','wqd'),('aaron','jeng')]
out = set([i for i in x])
print(list(out))
[('aaron', 'jeng'), ('sdf', 'wqd')]
That's a list of lists... But no matter, you can use a temporary set to make sure there are no repeats:
x = [['aaron','jeng'],['sdf','wqd'],['aaron','jeng']]
seen = set() # store here the visited tuples
y = [e for e in x if tuple(e) not in seen and not seen.add(tuple(e))]
# [['aaron', 'jeng'], ['sdf', 'wqd']]
If you convert your inner lists to tuples upfront it will have a considerably better performance.
If you don't need to preserve the order, then just convert the inner lists to tuples and turn your x to a set().
This would be easy with a list of tuples, you would simply need set(x). Since your list is a list of lists, and not a list of tuples, you can convert them first:
set(tuple(i) for i in x)
returns:
{('aaron', 'jeng'), ('sdf', 'wqd')}
Or, if you want to reconvert to a list of lists as you had it:
[list(t) for t in (set(tuple(i) for i in x))]
# [['aaron', 'jeng'], ['sdf', 'wqd']]
You can use enumerate and any:
x = [['aaron','jeng'],['sdf','wqd'],['aaron','jeng']]
new_x = [[a, b] for i, [a, b] in enumerate(x) if not any(c == b for _, c in x[:i])]
Output:
[['aaron', 'jeng'], ['sdf', 'wqd']]
You do not have tuples, you have lists inside lists.
x = [['aaron','jeng'],['sdf','wqd'],['aaron','jeng']]
uniques = list (set ( tuple(a) for a in x))
Is a generator expression fed into a set thats then fed to a list resulting in
[('aaron', 'jeng'), ('sdf', 'wqd')]
What about converting to a dict , Because dict can have unique keys :
x = [['aaron','jeng'],['sdf','wqd'],['aaron','jeng']]
print({tuple(i):i for i in x}.values())
output:
[['aaron', 'jeng'], ['sdf', 'wqd']]

How to loop though range and randomly shuffle a list in Python?

Given a list x = [1,0,0,1,1]I can use random.shuffle(x) repeatedly to shuffle this list, but if I try to do this a for loop the list doesn't shuffle.
For example:
x = [1,0,0,1,1]
k = []
for i in range(10):
random.shuffle(x)
k.append(x)
return x
Basically, kcontains the same sequence of x unshuffled? Any work around?
One pythonic way to create new random-orderings of a list is not to shuffle in place at all. Here is one implementation:
[random.sample(x, len(x)) for _ in range(10)]
Explanation
random.sample creates a new list, rather than shuffling in place.
len(x) is the size of the sample. In this case, we wish to output lists of the same length as the original list.
List comprehensions are often considered pythonic versus explicit for loops.
As mentioned by #jonrsharpe, random.shuffle acts on the list in place. When you append x, you are appending the reference to that specific object. As such, at the end of the loop, k contains ten pointers to the same object!
To correct this, simply create a new copy of the list each iteration, as follows. This is done by calling list() when appending.
import random
x = [1,0,0,1,1]
k = []
for i in range(10):
random.shuffle(x)
k.append(list(x))
Try this:
x = [1,0,0,1,1]
k = []
for i in range(10):
random.shuffle(x)
k.append(x.copy())
return x
By replacing x with x.copy() you append to k a new list that looks like x at that moment instead of x itself.

Put average of nested list values into new list

I have the following list:
x = [(27.3703703703704, 2.5679012345679, 5.67901234567901,
6.97530864197531, 1.90123456790123, 0.740740740740741,
0.440136054421769, 0.867718446601942),
(25.2608695652174, 1.73913043478261, 6.07246376811594,
7.3768115942029, 1.57971014492754, 0.710144927536232,
0.4875, 0.710227272727273)]
I'm looking for a way to get the average of each of the lists nested within the main list, and create a new list of the averages. So in the case of the above list, the output would be something like:
[[26.315],[2.145],[5.87],etc...]
I would like to apply this formula regardless of the amount of lists nested within the main list.
I assume your list of tuples of one-element lists is looking for the sum of each unpacked element inside the tuple, and a list of those options. If that's not what you're looking for, this won't work.
result = [sum([sublst[0] for sublst in tup])/len(tup) for tup in x]
EDIT to match changed question
result = [sum(tup)/len(tup) for tup in x]
EDIT to match your even-further changed question
result = [[sum(tup)/len(tup)] for tup in x]
An easy way to acheive this is:
means = [] # Defines a new empty list
for sublist in x: # iterates over the tuples in your list
means.append([sum(sublist)/len(sublist)]) # Put the mean of the sublist in the means list
This will work no matter how many sublists are in your list.
I would advise you read a bit on list comprehensions:
https://docs.python.org/2/tutorial/datastructures.html
It looks like you're looking for the zip function:
[sum(l)/len(l) for l in zip(*x)]
zip combines a collection of tuples or lists pairwise, which looks like what you want for your averages. then you just use sum()/len() to compute the average of each pair.
*x notation means pass the list as though it were individual arguments, i.e. as if you called: zip(x[0], x[1], ..., x[len(x)-1])
r = [[sum(i)/len(i)] for i in x]

Categories

Resources