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 working on a exercise and I can't see where I get it wrong. I'm trying to add the indexes of the sum of two numbers to a list, but instead of getting the indexes, I'm actually getting the numbers. Here is my code, and many thanks in advance for your precious help and time.
a_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
target_list = []
counter = 0
for i in range(len(a_list)):
for j in a_list:
if i + j == 10:
target_list.append((a_list.index(i), a_list.index(j)))
counter += 1
print(target_list)
how can I do it with list comprehension.
Thank you again and again.
You are getting the indexes, here is an example, if you change your list to:
a_list = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
The output would be different:
[(0, 1)]
what you did doesnt make any sense.. :
a_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
target_list = []
for i in range(len(a_list)):
for j in a_list:
if i + j == 10:
target_list.append((a_list.index(i), a_list.index(j)))
>>> target_list
[(1, 9), (2, 8), (3, 7), (4, 6), (5, 5), (6, 4), (7, 3), (8, 2), (9, 1)]
which is equal to :
a_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
target_list = []
for i in a_list:
for j in a_list:
if i + j == 10:
target_list.append((a_list.index(i), a_list.index(j)))
>>> target_list
[(1, 9), (2, 8), (3, 7), (4, 6), (5, 5), (6, 4), (7, 3), (8, 2), (9, 1)]
the point in python loops is that when you call for <item> in <Iterable>: it inserts the items to item and iterating each one by order, when you call range(len(list_a)) it generates a list from 0 to the length of a_list , that is eaqual to [0,1,2,3,4,5,6,7,8,9] and this is the same thing as you list...
you could also do the following:
target_list = [(i,j) for j in range(10) for i in range(10) if j+i ==10]
Target_list
>>>
[(9, 1), (8, 2), (7, 3), (6, 4), (5, 5), (4, 6), (3, 7), (2, 8), (1, 9)]
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've just written some code to convert a list of points into a list of to/from tuples but it doesn't feel very efficient.
I was wondering if anyone had any suggestions to make this more concise?
from_point, to_point = None, None
point_list = []
for p in [1, 5, 2, 4, 7, 9]:
to_point = p
if from_point and to_point:
point_list.append((from_point, to_point))
from_point = to_point
print(point_list)
Input: [1, 5, 2, 4, 7, 9]
Output: [(1, 5), (5, 2), (2, 4), (4, 7), (7, 9)]
Edit: Changed points to be non sequential.
You can always use zip:
>>> p = [1, 5, 2, 4, 7, 9]
>>> point_list = list(zip(p[:-1], p[1:]))
>>> print(point_list)
[(1, 5), (5, 2), (2, 4), (4, 7), (7, 9)]
An alternative one line solution
input = [1, 2, 3, 4, 5, 6]
output = [(input[index], input[index+1]) for index in range(len(list)-1)]
print(output)
What about this?
x=[1, 5, 2, 4, 7, 9]
print [ tuple(x[i:i+2]) for i in xrange(len(x)-1) ]
Using more_itertools:
import more_itertools as mit
list(mit.pairwise([1, 5, 2, 4, 7, 9]))
# [(1, 5), (5, 2), (2, 4), (4, 7), (7, 9)]
I need to iterate over n consecutive elements in a list.
For example:
data = [1,2,3,4,5,6,7]
I need to go over:
1 2
2 3
3 4
4 5
or:
1 2 3
2 3 4
3 4 5
4 5 6
Is there zip function to do that?
I'm not sure exactly what you're looking for, but try this:
data = [1, 2, 3, 4, 5, 6, 7]
n = 3
[data[i:i+n] for i in range(len(data) - n + 1)]
# [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7]]
Or:
f = lambda data, n: [data[i:i+n] for i in range(len(data) - n + 1)]
for x, y, z in f([1, 2, 3, 4, 5, 6, 7], 3):
print x, y, z
Assuming you are always doing this for a list or another sequence and it does not need to work with arbitrary iterables:
def group(seq, n):
return (seq[i:i+n] for i in range(len(seq)-n+1))
Examples:
>>> list(group([1,2,3,4,5,6,7], 2))
[[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]]
>>> list(group([1,2,3,4,5,6,7], 3))
[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7]]
If you need to do this for any arbitrary iterable (that may not support len() or slicing), you can adapt the pairwise recipe:
from itertools import tee, izip
def group(iterable, n):
"group(s, 3) -> (s0, s1, s2), (s1, s2, s3), (s2, s3, s4), ..."
itrs = tee(iterable, n)
for i in range(1, n):
for itr in itrs[i:]:
next(itr, None)
return izip(*itrs)
>>> list(group(iter([1,2,3,4,5,6,7]), 2))
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7)]
>>> list(group(iter([1,2,3,4,5,6,7]), 3))
[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6), (5, 6, 7)]
Specific answer:
>>> zip(data,data[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7)]
General answer:
>>> def consecutives(data,per_set):
... return zip(*[data[n:] for n in range(per_set)])
...
>>> consecutives(range(1,8),2)
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7)]
>>> consecutives(range(1,8),3)
[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6), (5, 6, 7)]
>>> consecutives(range(1,8),4)
[(1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6), (4, 5, 6, 7)]
Depending on whether you want to iterate over the sub-lists or a flat list:
from itertools import chain
for x in chain(*[ a[i:i+n] for i in xrange(len(a)-n+1) ]):
print x
Or:
for x in [ a[i:i+n] for i in xrange(len(a)-n+1) ]:
print x
Probably not the best way, but still useful:
>>> data = [1,2,3,4,5,6,7]
>>> map(None,data[:-1],data[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7)]
>>> map(None,data[:-2],data[1:-1],data[2:])
[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6), (5, 6, 7)]
This is a fairly simple task to program yourself. I dont think there is a pre-canned function to do this.
def func(arr,n):
i = 0
while i+n < len(arr):
for range(i,i+n):
.... make stuff here....
i = i + 1