Reputation: 965
I have two lists:
a = [1,3,6,10,20]
b = [2,4,9,12,15,22,24,25]
Now, I would like to make a new list, containing pairs from the two previous lists. The pairs are defined as such:
a[i]
b
between a[i]
and a[i+1]
if a[i+1]
exists, else just greater than a[i]
, if a[i]
exists, else just greater than a[-1]
with 0 < i < max(len(a),len(b))
The result would look like that:
pair = [[1,2],[3,4],[6,9],[10,15],[20,25]]
Anyone knows how to do that ?
This is what I have done so far:
a = [1,3,6,10,20]
b = [2,4,9,12,15,22,24,25]
pairs = []
counter = 0
for i in range(max(len(a),len(b))):
try:
# get a[i]
ai = a[i]
except:
ai = a[-1]
try:
# get a[i+1]
ai1 = a[i+1]
except:
ai1 = b[-1]+1
temp = []
for bi in b:
if ai < bi and bi < ai1:
temp.append(bi)
# Avoid adding the last element of b again and again until i = len(b)
if max(temp) == b[-1]:
counter = counter +1
if counter <= 1:
print(max(temp))
pairs.append([ai,max(temp)])
It's okay, since it gets the job done, but I was wondering, if there is a better, more efficient way to do it ?
Upvotes: 3
Views: 1022
Reputation: 1858
Here is another way of doing it:
a = [1,3,6,10,20]
b = [2,4,9,12,15,22,24,25]
merged = sorted(a + b, reverse=True)
mask = [(False, True)[x in a] for x in merged]
flag = True
good = []
for m, n in zip(mask, merged):
if m is flag:
continue
else:
good.append(n)
flag = not flag
pairs = list(zip(good[1::2], good[::2]))[::-1]
pairs
>>> [(1, 2), (3, 4), (6, 9), (10, 15), (20, 25)]
Upvotes: 1
Reputation: 11476
You can do a binary search, since the arrays are sorted, you don't have to search for a[i] < b[j]
, only for a[i+1] > b[j]
(This code will return invalid results if there are no elements in b
such that a[i] < b < a[b+1]
):
import bisect
def pairs(a, b):
for (a1, a2) in zip(a, a[1:]):
yield a1, b[bisect.bisect_left(b, a2) - 1]
yield a[-1], b[-1]
print(list(pairs([1,3,6,10,20], [2,4,9,12,15,22,24,25])))
[(1, 2), (3, 4), (6, 9), (10, 15), (20, 25)]
Upvotes: 1