Comparing two lists and performing an operation in Python

Viewed 36

I have two lists I and i. I want to find for each element of i, how many values are less than in I and add the total number of such values to the specific i element. For example, element 15 in i has two values less than itself in I i.e. [8,11]. So 2 should be added to 15 and the combination stored in Values. I present the expected output.

I = [8, 11, 19, 37, 40, 42]

i=[15, 17, 27, 28, 31, 41]

The expected output is

New i=[17,19,30,31,34,46]
Values=[[8,11],[8,11],[8,11,19],[8,11,19],[8,11,19],[8,11,19,37,40]]
4 Answers

Assuming your list I is sorted, you can use bisect_left to get insertion point in your list I for each element in i and then slice the list. It uses binary search.

With that you can do:

from bisect import bisect_left
Values = [I[:bisect_left(I, e)] for e in i]
New_i =  [e + len(Values[j]) for j, e in enumerate(i)]

print(Values):

[[8, 11], [8, 11], [8, 11, 19], [8, 11, 19], [8, 11, 19], [8, 11, 19, 37, 40]]

print(New_i):

[17, 19, 30, 31, 34, 46]

BTW I highly recommend not to use I and i for your variable names.

You can use two list comprehensions

>>> # for each element in i, add the elements in I to a list if they are smaller
>>> values = [[e for e in I if e < n] for n in i]
>>> # add the element of i to the number of elements in I that are smaller
>>> new_i = [sum(x) for x in zip(i, map(len, values))]
>>> values
[[8, 11], [8, 11], [8, 11, 19], [8, 11, 19], [8, 11, 19], [8, 11, 19, 37, 40]]
>>> new_i
[17, 19, 30, 31, 34, 46]

the other solutions are 100% correct, here's another solution but oldschool and more readable:

l1 = [15, 17, 27, 28, 31, 41]
l2 = [8, 11, 19, 37, 40, 42]
comp = []
for i in l1:
    c = []
    for j in l2:
        if i > j:
            i += 1
            c.append(j)
    comp.append(c)
print(l1)
print(comp)

input >>

l1 = [15, 17, 27, 28, 31, 41]

l2 = [8, 11, 19, 37, 40, 42]

output >>

[15, 17, 27, 28, 31, 41]

[[8, 11], [8, 11], [8, 11, 19], [8, 11, 19], [8, 11, 19], [8, 11, 19, 37, 40, 42]]

One way to do this is to use numpy which allows quick operations on lists by putting them in matrix form and is more optimized than operations in lists. An example of code could be:

import numpy as np

list_1 = [8, 11, 19, 37, 40, 42]
list_2 = [15, 17, 27, 28, 31, 41]

arr_1, arr_2 = np.array(list_1), np.array(list_2)
# Broadcast to 2D array where elem (i, j) is whether list_2[i] < list_1[j] or not
arr_sup = (arr_2[:, None] - arr_1[None, :]) > 0
# Add sum of rows to list_2 to create the new list
new_list = (np.sum(arr_sup, axis=1) + list_2).tolist()
# Get indexes (i, j) where arr_sup[i, j] is True
idx_sup = np.where(arr_sup)
values = []
for i, j in zip(idx_sup[0], idx_sup[1]):  # browse i and j together
    if len(values) < i + 1:
        # Add a new list for each new i
        values.append([])
    # Add value j of list 1 to i-th list in values
    values[i].append(list_1[j])

print(new_list) # [17, 19, 30, 31, 34, 46]
print(values) # [[8, 11], [8, 11], [8, 11, 19], [8, 11, 19], [8, 11, 19], [8, 11, 19, 37, 40]]

It works even if the lists are not sorted.

Related