user20032724
user20032724

Reputation: 163

Comparing two lists and performing an operation in Python

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]]

Upvotes: 0

Views: 80

Answers (4)

Valentin Goldité
Valentin Goldité

Reputation: 1219

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.

Upvotes: 0

Hannon qaoud
Hannon qaoud

Reputation: 958

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]]

Upvotes: 0

SomeDude
SomeDude

Reputation: 14228

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.

Upvotes: 3

ChrisOram
ChrisOram

Reputation: 1434

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]

Upvotes: 2

Related Questions