Related
I have 2 arrays:
[7, 6, 9, 8]
[1, 2, 3, 4, 5, 3, 2, 1]
I want to slide across them like so:
Iteration 1:
[7, 6, 9, |8|]
[|1|, 2, 3, 4, 5, 3, 2, 1]
2:
[7, 6, |9, 8|]
[|1, 2|, 3, 4, 5, 3, 2, 1]
3:
[7,|6, 9, 8|]
[|1, 2, 3|, 4, 5, 3, 2, 1]
4:
[|7, 6, 9, 8|]
[|1, 2, 3, 4|, 5, 3, 2, 1]
5:
[|7, 6, 9, 8|]
[1, |2, 3, 4, 5|, 3, 2, 1]
And it keeps going at the first array's length until...
Iteration 9:
[|7, 6, 9|, 8|]
[1, 2, 3, 4, 5, |3, 2, 1|]
10:
[|7, 6|, 9, 8|]
[1, 2, 3, 4, 5, 3, |2, 1|]
11:
[|7|, 6, 9, 8|]
[1, 2, 3, 4, 5, 3, 2, |1|]
What have I already tried? A mess that just doesn't work, and I'm afraid sharing it will discourage many from even responding.
EDIT: Here's my non-working code for those who wanted to see it:
embedding_list_1 = [[1, 2, 3], [1, 3, 4], [1, 2, 4]]
embedding_list_2 = [[1, 2, 3], [1, 3, 4], [1, 2, 4], [1, 2, 4], [1, 2, 4], [3, 4, 5]]
region_range = 1
first_run = True
increment = True
embedding_list_2_start = 0
embedding_list_2_end = len(embedding_list_1)
while region_range >= 0:
if first_run:
print('Cutting embedding list 1 from:', len(embedding_list_1)-region_range, 'to', len(embedding_list_1))
print(embedding_list_1[len(embedding_list_1)-region_range:])
print('Cutting embedding list 2 from:', 0, 'to', region_range)
embedding_list_2[:region_range]
region_range +=1
first_run = False
else:
chopped_off = embedding_list_1[len(embedding_list_1)-region_range:]
print(chopped_off)
embedding_list_2[embedding_list_2_start:region_range]
if increment:
region_range +=1
if region_range == len(embedding_list_1):
#break
#use full list
print(len(embedding_list_1))
embedding_list_2_start+=1
embedding_list_2_end+=1
print('Cutting embedding list 2 from', embedding_list_2_start, 'to', embedding_list_2_end)
print(embedding_list_2[embedding_list_2_start:embedding_list_2_end])
increment = False
if embedding_list_2_end == len(embedding_list_2):
#Stop incrementing end
#Start negative shift for other embedding
region_range-=1
print('Cutting embedding list 1 from: 0', 'to', region_range)
embedding_list_1[0:region_range]
embedding_list_2_start+=1
embedding_list_2_end+=1
print('cuting embedding list 2 from:', embedding_list_2_start, embedding_list_2_end)
embedding_list_2[:embedding_list_2_end]
Here's a quick, possibly quite dirty attempt.
The overlap looks like this in the first iteration:
Let's look at everything relative to list2 first. In the first iteration
# Calculate the offset between the two lists
offset = 1 - len(list1) # -3
l2_window_start = offset
l2_window_end = 0
# The slice for list2 starts at the larger of 0 and l2_window_start
l2_start = max(0, l2_window_start)
# The slice for list2 ends at the smaller of 7 and l2_window_end
l2_end = min(len(list2) - 1, l2_window_end)
# Add one to l2_end because slices don't contain the end index.
list2_slice = list2[l2_start:l2_end+1]
Now, looking at list1 using these numbers:
l1_window_start = -offset # starts off at 3
l1_start = max(0, l1_window_start)
# list1 slice needs to have as many elements as list2_slice
l1_end = l1_start + len(list2_slice)
list1_slice = list1[l1_start:l1_end]
As the iterations move forward, l2_window_start, l2_window_end and offset all increase by 1. l1_window_start decreases by 1.
Putting this in a loop:
list1 = [7, 6, 9, 8]
list2 = [1, 2, 3, 4, 5, 3, 2, 1]
offset = l2_window_start = 1 - len(list1) # -3
l2_window_end = 0
l1_window_start = -offset
l1_window_end = len(list1) - 1
for iternum in range(11):
# The slice for list2 starts at the larger of 0 and l2_window_start
l2_start = max(0, l2_window_start)
# The slice for list2 ends at the smaller of 7 and l2_window_end
l2_end = min(len(list2) - 1, l2_window_end)
# Add one to l2_end because slices don't contain the end index.
list2_slice = list2[l2_start:l2_end+1]
l1_start = max(0, l1_window_start)
l1_end = l1_start + len(list2_slice)
list1_slice = list1[l1_start:l1_end]
print(iternum+1, list1_slice, list2_slice)
l1_window_start -= 1;
l2_window_start += 1; l2_window_end += 1; offset += 1
Which gives us the required output:
1 [8] [1]
2 [9, 8] [1, 2]
3 [6, 9, 8] [1, 2, 3]
4 [7, 6, 9, 8] [1, 2, 3, 4]
5 [7, 6, 9, 8] [2, 3, 4, 5]
6 [7, 6, 9, 8] [3, 4, 5, 3]
7 [7, 6, 9, 8] [4, 5, 3, 2]
8 [7, 6, 9, 8] [5, 3, 2, 1]
9 [7, 6, 9] [3, 2, 1]
10 [7, 6] [2, 1]
11 [7] [1]
My solution is very similar (maybe ultimately the same) as #pranav-hosangadi's answer. I produce a slightly different result as my answer produces tuples based on pairing up the windowed elements from each list.
As with #pranav-hosangadi's answer, we start with ranging over a range that encompasses the full slide. The tricky part (at least for me) was working out the right starts and ends.
a = [7, 6, 9, 8]
b = [1, 2, 3, 4, 5, 3, 2, 1]
a_len = len(a)
b_len = len(b)
for i in range(0, a_len + b_len -1):
a_start = max(0, a_len -i -1)
a_end = min(a_len, a_len + b_len - i)
b_start = max(0, i + 1 - a_len)
b_end = min(i + 1, b_len)
result = [(a[x], b[y]) for (x, y) in zip(range(a_start, a_end), range(b_start, b_end))]
print(result)
This produces the slightly different (wrong?) output:
[(8, 1)]
[(9, 1), (8, 2)]
[(6, 1), (9, 2), (8, 3)]
[(7, 1), (6, 2), (9, 3), (8, 4)]
[(7, 2), (6, 3), (9, 4), (8, 5)]
[(7, 3), (6, 4), (9, 5), (8, 3)]
[(7, 4), (6, 5), (9, 3), (8, 2)]
[(7, 5), (6, 3), (9, 2), (8, 1)]
[(7, 3), (6, 2), (9, 1)]
[(7, 2), (6, 1)]
[(7, 1)]
Here is a slightly different variation on using the zip function;
l1 = [7, 6, 9, 8]
l2 = [1, 2, 3, 4, 5, 3, 2, 1]
def slide(la, lb):
lxa = []
lxa = [x for x in range(len(la))]
lxa.extend([None]* (len(lb) - 1))
lxb = [None] * (len(la) -1)
lxb.extend([x for x in range(len(lb))])
lxcnt = 0
rslt = []
while lxcnt < len(lxa):
tmp = []
matchs = zip(lxa, lxb)
for mtch in matchs:
if mtch[0] != None and mtch[1] != None:
tmp.append(mtch)
if tmp:
rslt.append(tmp)
lxa.insert(0, None)
lxa = lxa[:-1]
lxcnt += 1
return rslt
running slide(l1, l2) , yields:
[[(3, 0)],
[(2, 0), (3, 1)],
[(1, 0), (2, 1), (3, 2)],
[(0, 0), (1, 1), (2, 2), (3, 3)],
[(0, 1), (1, 2), (2, 3), (3, 4)],
[(0, 2), (1, 3), (2, 4), (3, 5)],
[(0, 3), (1, 4), (2, 5), (3, 6)],
[(0, 4), (1, 5), (2, 6), (3, 7)],
[(0, 5), (1, 6), (2, 7)],
[(0, 6), (1, 7)],
[(0, 7)]]
I am new to Python and I would like to combine two arrays. I have two arrays: A and B and would like to get array C as follows:
A = [1, 2, 3, 4, 5]
B = [6, 7, 8, 9, 10]
Result array:
C = [(1, 6), (2, 7), (3, 8), (4, 9), (5, 10)]
Use zip, the built-in for pairwise iteration:
C = list(zip(A, B))
Note that you are not concatenating the two lists.
Without any dependency:
>>> A = [1, 2, 3, 4, 5]
>>> B = [6, 7, 8, 9, 10]
>>> C = [(A[i], B[i]) for i in range(len(A))]
>>> C
[(1, 6), (2, 7), (3, 8), (4, 9), (5, 10)]
I am able to produce all combinations given a particular value (k) for a single list as follows:
lst = []
p = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
c = itertools.combinations(p, k)
for i in c:
lst.append(list(i))
print lst
Note, in this code, k requires a specific value to be inputted - it cannot be a variable.
However, I now have multiple lists in which I need all combinations for various k:
m = [1, 2, 3, 4]
t = [1, 2, 3, 4]
c = [1, 2, 3, 4, 5]
ss =[1, 2, 3]
Put simply: I require an output of all the combinations possible for all these lists. E.g. k = 1 through 4 for m and t, 1 through 5 for c, and 1 through 3 for ss.
Example of k = 2 for ss would be
m = [1, 2, 3, 4]
t = [1, 2, 3, 4]
c = [1, 2, 3, 4, 5]
ss = [1, 2]
m = [1, 2, 3, 4]
t = [1, 2, 3, 4]
c = [1, 2, 3, 4, 5]
ss = [1, 3]
m = [1, 2, 3, 4]
t = [1, 2, 3, 4]
c = [1, 2, 3, 4, 5]
ss = [2, 3]
Follow this pattern for all values combinations of k possible in all variables.
Let me know if this is unclear and I can edit question accordingly.
You can get your output via itertools.product alone or via combinations. We could cram this all into one line if we really wanted, but I think it's more comprehensible to write
from itertools import combinations, product
def all_subs(seq):
for i in range(1, len(seq)+1):
for c in combinations(seq, i):
yield c
after which we have
>>> m,t,c,ss = [1,2,3,4],[1,2,3,4],[1,2,3,4,5],[1,2,3]
>>> seqs = m,t,c,ss
>>> out = list(product(*map(all_subs, seqs)))
>>> len(out)
48825
which is the right number of results:
>>> (2**4 - 1) * (2**4 - 1) * (2**5-1) * (2**3 - 1)
48825
and hits every possibility:
>>> import pprint
>>> pprint.pprint(out[:4])
[((1,), (1,), (1,), (1,)),
((1,), (1,), (1,), (2,)),
((1,), (1,), (1,), (3,)),
((1,), (1,), (1,), (1, 2))]
>>> pprint.pprint(out[-4:])
[((1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4, 5), (1, 2)),
((1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4, 5), (1, 3)),
((1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4, 5), (2, 3)),
((1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4, 5), (1, 2, 3))]
I'm having trouble unpacking a 2-dimensional list of tuples (or rather, I'm looking for a more elegant solution).
The list is as shown:
a = [ [(2, 3, 5), (3, 4, 6), (4, 5, 7), (1, 1, 1), (1, 2, 3)],
[(4, 9, 2), (8, 8, 0), (3, 5, 1), (2, 6, 8), (2, 4, 8)],
[(8, 7, 5), (2, 5, 1), (9, 2, 2), (4, 5, 1), (0, 1, 9)], ...]
And I want to unpack the tuples to obtain 3 nested lists of the same form, i.e.:
a_r = [ [2, 3, 4, 1, 1] , [4, 8, 3, 2, 2] , [8, 2, 9, 4, 0] , ...]
a_g = [ [3, 4, 5, 1, 2] , [9, 8, 5, 6, 4] , [7, 5, 2, 5, 1] , ...]
and so on. Here is my code:
a_r = []
a_g = []
a_b = []
for i in xrange(len(a)):
r0=[]
g0=[]
b0=[]
for j in range(5):
r0.append(a[i][j][0])
g0.append(a[i][j][1])
b0.append(a[i][j][2])
a_r.append(r0)
a_g.append(g0)
a_b.append(b0)
I'm sure there are more efficient ways to do this (I've just begun learning Python). This question is similar, but I wasn't able to follow the functional programming.
Thanks!
I think you are after something like this:
a = [ [(2, 3, 5), (3, 4, 6), (4, 5, 7), (1, 1, 1), (1, 2, 3)],
[(4, 9, 2), (8, 8, 0), (3, 5, 1), (2, 6, 8), (2, 4, 8)],
[(8, 7, 5), (2, 5, 1), (9, 2, 2), (4, 5, 1), (0, 1, 9)]]
for row in a:
print(list(zip(*row)))
Which gives:
[(2, 3, 4, 1, 1), (3, 4, 5, 1, 2), (5, 6, 7, 1, 3)]
[(4, 8, 3, 2, 2), (9, 8, 5, 6, 4), (2, 0, 1, 8, 8)]
[(8, 2, 9, 4, 0), (7, 5, 2, 5, 1), (5, 1, 2, 1, 9)]
The resulting tuples are same as in your example, but different order. I dont understand how you ordered them. If you could clarify this, I might modify the example.
Hope this helps.
>>> a = [ [(2, 3, 5), (3, 4, 6), (4, 5, 7), (1, 1, 1), (1, 2, 3)],
... [(4, 9, 2), (8, 8, 0), (3, 5, 1), (2, 6, 8), (2, 4, 8)],
... [(8, 7, 5), (2, 5, 1), (9, 2, 2), (4, 5, 1), (0, 1, 9)]]
>>> zip(*(zip(*x) for x in a))
[((2, 3, 4, 1, 1), (4, 8, 3, 2, 2), (8, 2, 9, 4, 0)), ((3, 4, 5, 1, 2), (9, 8, 5, 6, 4), (7, 5, 2, 5, 1)), ((5, 6, 7, 1, 3), (2, 0, 1, 8, 8), (5, 1, 2, 1, 9))]
>>> for row in _:
... print row
...
((2, 3, 4, 1, 1), (4, 8, 3, 2, 2), (8, 2, 9, 4, 0))
((3, 4, 5, 1, 2), (9, 8, 5, 6, 4), (7, 5, 2, 5, 1))
((5, 6, 7, 1, 3), (2, 0, 1, 8, 8), (5, 1, 2, 1, 9))
If it must be lists
>>> map(list, zip(*(map(list, zip(*x)) for x in a)))
[[[2, 3, 4, 1, 1], [4, 8, 3, 2, 2], [8, 2, 9, 4, 0]], [[3, 4, 5, 1, 2], [9, 8, 5, 6, 4], [7, 5, 2, 5, 1]], [[5, 6, 7, 1, 3], [2, 0, 1, 8, 8], [5, 1, 2, 1, 9]]]
>>> for row in _:
... print row
...
[[2, 3, 4, 1, 1], [4, 8, 3, 2, 2], [8, 2, 9, 4, 0]]
[[3, 4, 5, 1, 2], [9, 8, 5, 6, 4], [7, 5, 2, 5, 1]]
[[5, 6, 7, 1, 3], [2, 0, 1, 8, 8], [5, 1, 2, 1, 9]]
Tuples are immutable (meaning you cannot change them), so you're going to have to go through every element to extract them. That is essentially what the functional programming example you linked to is doing, in a very pythonic, list comprehension, way.
To help you help yourself, as shirdharama says, take a look at the example again and know that fmap_lol really means "function mapping - list of lists", fmap_list means "function mapping - list", and fmap_el means "function mapping - element". So split_nt calls fmap_lol, which splits your input in a list of lists (the tuples), calls fmap_list, which takes each list and calls fmap_el, which returns the element back up the chain.
The example is just a way to walk through the tuples to extract every element and put them where you wish. It's functional because they are functions calls, not a single line of later forgotten gobbligook.
If you're unfamiliar with list comprehensions, lamda (or anonymous functions), or anything else in the example I suggest spending some time with the python documentation and looking each up.
How to generate something like
[(), (1,), (1,2), (1,2,3)..., (1,2,3,...n)]
and
[(), (4,), (4,5), (4,5,6)..., (4,5,6,...m)]
then take the product of them and merge into
[(), (1,), (1,4), (1,4,5), (1,4,5,6), (1,2), (1,2,4)....(1,2,3,...n,4,5,6,...m)]
?
For the first two lists I've tried the powerset recipe in https://docs.python.org/2/library/itertools.html#recipes , but there will be something I don't want, like (1,3), (2,3)
For the product I've tested with chain and product, but I just can't merge the combinations of tuples into one.
Any idea how to do this nice and clean? Thanks!
Please note that, single element tuples are denoted like this (1,).
a = [(), (1,), (1, 2), (1, 2, 3)]
b = [(), (4,), (4, 5), (4, 5, 6)]
from itertools import product
for item1, item2 in product(a, b):
print item1 + item2
Output
()
(4,)
(4, 5)
(4, 5, 6)
(1,)
(1, 4)
(1, 4, 5)
(1, 4, 5, 6)
(1, 2)
(1, 2, 4)
(1, 2, 4, 5)
(1, 2, 4, 5, 6)
(1, 2, 3)
(1, 2, 3, 4)
(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5, 6)
If you want them in a list, you can use list comprehension like this
from itertools import product
print [sum(items, ()) for items in product(a, b)]
Or even simpler,
print [items[0] + items[1] for items in product(a, b)]
You can try like this,
>>> a=[(), (1,), (1,2), (1,2,3)]
>>> b=[(), (4,), (4,5), (4,5,6)]
>>> for ix in a:
... for iy in b:
... print ix + iy
...
()
(4,)
(4, 5)
(4, 5, 6)
(1,)
(1, 4)
(1, 4, 5)
(1, 4, 5, 6)
(1, 2)
(1, 2, 4)
(1, 2, 4, 5)
(1, 2, 4, 5, 6)
(1, 2, 3)
(1, 2, 3, 4)
(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5, 6)
If you don't want to use any special imports:
start = 1; limit = 10
[ range(start, start + x) for x in range(limit) ]
With start = 1 the output is:
[[], [1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7, 8, 9]]
If you want to take the product, maybe using itertools might be most elegant.