Related
I want my code to return, for every element in array, this array but without this one element.
Example: for array numbers=[1,2,3] I want output "[2,3]","[1,3]","[1,2]"
I've used this code:
examp = [1, 2, 3, 4, 5]
for number in examp:
print(str(number) + " MAIN")
subExp = examp
subExp.remove(number)
print(subExp)
but this one outputs (word "MAIN" is used as information which element is right now "subtracted" from array):
1 MAIN
[2, 3, 4, 5]
3 MAIN
[2, 4, 5]
5 MAIN
[2, 4]
For this code above I would expect this:
1 MAIN
[2, 3, 4, 5]
2 MAIN
[1, 3, 4, 5]
3 MAIN
[1, 2, 4, 5]
4 MAIN
[1, 2, 3, 5]
5 MAIN
[1, 2, 3, 4]
It's probably some stupid mistake from my side, but as a beginner in this topic, I coudn't find answer anywhere, so if there's any better way to do it, please help
The issue is this line:
subExp = examp
Here subExp isn't a copy of examp, but rather just another pointer just like examp to the list [1, 2, 3, 4, 5]. So in each iteration of your for loop you remove one entry of the list.
You can replace that line with:
subExp = examp.copy()
which will make a shallow copy of examp. Although this works for flat lists, you'd get in trouble for nested lists. In general you want to use copy package's
subExp = copy.deepcopy(examp)
EDIT: If you don't need to do the print line, then itertools.combinations() is the way to go. See https://docs.python.org/2/library/itertools.html#itertools.combinations for more info
For these you can use itertools:
import itertools
list(itertools.combinations([1, 2, 3,4,5],4))
# [(1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 4, 5), (1, 3, 4, 5), (2, 3, 4, 5)]
Iterate through the list, slicing out the current element:
examp = [7, False, "OOpS", 3.14159]
for i in range(len(examp)):
print(examp[:i] + examp[i+1:])
Output:
[False, 'OOpS', 3.14159]
[7, 'OOpS', 3.14159]
[7, False, 3.14159]
[7, False, 'OOpS']
You can create a range, then output arrays filtered by index
examp = [1, 2, 3, 4, 5]
for x in range(0, len(examp)):
print(f'iteration {x + 1} ->')
print([el for i, el in enumerate(examp) if i != x])
or using itertools
print(list(itertools.combinations(examp, len(examp) - 1)))
I'm trying to make a general way to generate all the combinations of multiple ranges or lists, for example,
[range(0, 2), range(2, 5), range(4, 6), range(2, 3)],
which should return a 2x3x2x1 = 12 element list.
[[0, 2, 4, 2],
[0, 2, 5, 2],
[0, 3, 4, 2],
[0, 3, 5, 2],
[0, 4, 4, 2],
[0, 4, 5, 2],
[1, 2, 4, 2],
[1, 2, 5, 2],
[1, 3, 4, 2],
[1, 3, 5, 2],
[1, 4, 4, 2],
[1, 4, 5, 2]]
So far, everything is fine here. When I hardcode it, by doing
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
x.append( ( a + [b] for a in x[-1] for b in rgs[2]) )
x.append( ( a + [b] for a in x[-1] for b in rgs[3]) )
I get the good result. However, when I attempt to generalize it, by doing
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
for i in range(1,len(rgs)-1):
x.append( ( a + [b] for a in x[-1] for b in rgs[i+1]) )
I obtain a 6-element list:
[[0, 2, 2, 2],
[0, 3, 2, 2],
[0, 4, 2, 2],
[1, 2, 2, 2],
[1, 3, 2, 2],
[1, 4, 2, 2]]
Also, what I notice is that all the ranges generated after the first two use the range in rgs[-1] instead of the correct ones. I struggle to understand why this happens, as I beleive that those two code example are identical, except the latter is the more general form for arbitrary large number of ranges.
You can use itertools.product to output a list of tuples
Input:
import itertools
a= [range(0, 2), range(2, 5), range(4, 6), range(2, 3)]
list(itertools.product(*a))
Output:
[(0, 2, 4, 2),
(0, 2, 5, 2),
(0, 3, 4, 2),
(0, 3, 5, 2),
(0, 4, 4, 2),
(0, 4, 5, 2),
(1, 2, 4, 2),
(1, 2, 5, 2),
(1, 3, 4, 2),
(1, 3, 5, 2),
(1, 4, 4, 2),
(1, 4, 5, 2)]
I did not get the same result when running your first code. I had to change it up a bit:
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
x.append( ( a + [b] for a in x[-1] for b in rgs[2]) )
x = list( a + [b] for a in x[-1] for b in rgs[3])
Most people that don't know about itertools would have done it this way:
x=[]
for i0 in rgs[0]:
for i1 in rgs[1]:
for i2 in rgs[2]:
for i3 in rgs[3]:
x.append([i0,i1,i2,i3])
Or using a list comprehension (DON'T DO THIS, it is VERY messy looking):
[[i0,i1,i2,i3] for i3 in rgs[3] for i2 in rgs[2] for i1 in rgs[1] for i0 in rgs[0]]
Your issue has to do with creating generator expressions in a loop. Generator expressions are implemented as functions, and like functions, they can have "free" variables that they look up in the containing namespaces. Your generator expressions are accessing the i from outside their definition, and because of this, they end up seeing a different i value you expect.
Here's an example that might be easier to understand:
def gen()
print(i)
yield 10
x = []
for i in range(3):
x.append(gen()) # add several generators while `i` has several different values
for g in x:
list(g) # consume the generators, so they can print `i`
Here, rather than using the i value for something useful, I've written a generator function that just prints it out. If you run this code, you'll see that all the generators print out 2, since that's the value of i when they finally run (after the first loop ended).
Your situation is a little more subtle, as you're consuming the previous generator as you create the next one, but the general idea is the same. The generator expression loop that you expect to be over rgs[2] is actually over rgs[3] because it's actually being looked up with rgs[i+1] and i increased between the time the generator expression was declared and when it was consumed.
I am looking for some help splitting an index from a list containing multiple values and creating a new list with separated values.
L = [(1, 2, 2, 3, 4, 4, 5, 5)]
>>>L[0]
(1, 2, 2, 3, 4, 4, 5, 5)
I need to split that single index into multiple indices in a new list such that:
L_Revised = [1, 2, 2, 3, 4, 4, 5, 5]
>>>L[0]
1
So that I can manipulate the individual indices. What code could I use for this?
Thanks for any help!
For a generalized case, where you can have more than one tuple in the list, you can flatten your list like this:
>>> l = [(1, 2, 3, 4, 5)]
>>> [item for tup in l for item in tup]
[1, 2, 3, 4, 5]
But if it's a single tuple element list, then probably other answer is easier.
Say we create a list like so in python:
[[1, 2, 3], [1, 3, 4], [2, 4, 5]]
And then I want to take 1+1+2 and divide by 3, giving me the average for that element and store in a new list. I want to do that again for the second elements and lastly for the third. How would one do it succinctly? (I cannot think of a way other than multiple loops.)
The output should be a new list [(1+1+2), (2+3+4), (3+4+5)]
Thanks so much!
Averages:
>>> data = [[1, 2, 3], [1, 3, 4], [2, 4, 5]]
>>> from __future__ import division
>>> [sum(e)/len(e) for e in zip(*data)]
[1.3333333333333333, 3.0, 4.0]
Sums:
>>> data = [[1, 2, 3], [1, 3, 4], [2, 4, 5]]
>>> [sum(e) for e in zip(*data)]
[4, 9, 12]
zip
returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables.
Unpacking argument lists
when the arguments are already in a list or tuple but need to be unpacked for a function call requiring separate positional arguments ... write the function call with the *-operator to unpack the arguments out of a list or tuple.
>>> data
[[1, 2, 3], [1, 3, 4], [2, 4, 5]]
>>> zip(*data)
[(1, 1, 2), (2, 3, 4), (3, 4, 5)]
>>> l = [[1, 2, 3], [1, 3, 4], [2, 4, 5]]
>>> zip(*l)
[(1, 1, 2), (2, 3, 4), (3, 4, 5)]
>>> def average(nums, default=float('nan')):
... return sum(nums) / float(len(nums)) if nums else default
...
>>> [average(n) for n in zip(*l)]
[2.0, 2.6666666666666665, 3.6666666666666665]
I have a list [2,3,4]. How do I find all possible sequence of elements in the list?
So the output should be:
[2,3,4]
[2,4,3]
[3,2,4]
[3,4,2]
[4,2,3]
[4,3,2]
You can do this easily using itertools.permutations():
>>> from itertools import permutations
>>> list(permutations([2, 3, 4]))
[(2, 3, 4), (2, 4, 3), (3, 2, 4), (3, 4, 2), (4, 2, 3), (4, 3, 2)]
And if for some reason you need lists instead of tuples:
>>> map(list, permutations([2, 3, 4]))
[[2, 3, 4], [2, 4, 3], [3, 2, 4], [3, 4, 2], [4, 2, 3], [4, 3, 2]]
You are looking for permutations, something like this should work:
import itertools
itertools.permutations([2,3,4])
a start of a great lottery program except data would be formated as such
ist(permutations([2, 3, 4],[7,2,5],[8,1,4,9]))
the problem is that the first group is used to create numbers in first column only
the secound is for 2 column and 3rd is for 3rd
the output will be a set of 3 numbers just that the permutation is different
Just so you know:
def unique_perms(elems):
"""returns non-duplicate permutations
if duplicate elements exist in `elems`
"""
from itertools import permutations
return list(set(permutations(elems)))
But if you're doing something like this:
print len(unique_perms(elems))
Then try this:
def fac(n):
"""n!"""
if n == 1: return n
return n * fac(n -1)
def unique_perm_count(elems)
n = len(elems)
return fac(2 * n) / fac(n) ** 2