First Python List Index Greater Than X

First Python list index greater than x?

next(x[0] for x in enumerate(L) if x[1] > 0.7)

Find the indices of elements greater than x

OK, I understand what you mean and a Single line of Python will be enough:

using list comprehension

[ j for (i,j) in zip(a,x) if i >= 4 ]
# a will be the list compare to 4
# x another list with same length

Explanation:
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j']

Zip function will return a list of tuples

>>> zip(a,x)
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f'), (7, 'g'), (8, 'h'), (9, 'j')]

List comprehension is a shortcut to loop an element over list which after "in", and evaluate the element with expression, then return the result to a list, also you can add condition on which result you want to return

>>> [expression(element) for **element** in **list** if condition ]

This code does nothing but return all pairs that zipped up.

>>> [(i,j) for (i,j) in zip(a,x)]
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f'), (7, 'g'), (8, 'h'), (9, 'j')]

What we do is to add a condition on it by specify "if" follow by a boolean expression

>>> [(i,j) for (i,j) in zip(a,x) if i >= 4]
[(4, 'd'), (5, 'e'), (6, 'f'), (7, 'g'), (8, 'h'), (9, 'j')]

using Itertools

>>> [ _ for _ in itertools.compress(d, map(lambda x: x>=4,a)) ]
# a will be the list compare to 4
# d another list with same length

Use itertools.compress with single line in Python to finish close this task

>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> d = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j'] # another list with same length
>>> map(lambda x: x>=4, a) # this will return a boolean list
[False, False, False, True, True, True, True, True, True]

>>> import itertools
>>> itertools.compress(d, map(lambda x: x>4, a)) # magic here !
<itertools.compress object at 0xa1a764c> # compress will match pair from list a and the boolean list, if item in boolean list is true, then item in list a will be remain ,else will be dropped
#below single line is enough to solve your problem
>>> [ _ for _ in itertools.compress(d, map(lambda x: x>=4,a)) ] # iterate the result.
['d', 'e', 'f', 'g', 'h', 'j']

Explanation for itertools.compress, I think this will be clear for your understanding:

>>> [ _ for _ in itertools.compress([1,2,3,4,5],[False,True,True,False,True]) ]
[2, 3, 5]

Finding list indexes of numbers greater than a value

You can simply iterate through the list and break when you condition is true:

test_list = [1,5,7,11,20,26,89]
for i, value in enumerate(test_list):
if value > 13:
break

print(value) # 20
print(i) # 4

In Python, how do you find the index of the first value greater than a threshold in a sorted list?

Have a look at bisect.

import bisect

l = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

bisect.bisect(l, 55) # returns 7

Compare it with linear search:

timeit bisect.bisect(l, 55)
# 375ns

timeit next((i for i,n in enumerate(l) if n > 55), len(l))
# 2.24us

timeit next((l.index(n) for n in l if n > 55), len(l))
# 1.93us

Efficient solution to find list indices greater than elements in a second list

So I found there is a numpy function to perform this task, np.searchsorted. which is much faster than the use of list comprehensions.

result=np.searchsorted(searchlist,newindices)

These are the timings for the various solutions:

1. Standard List comprehension:

this was my first attempt at a solution

python3 -m timeit -s "import numpy as np" -s "import bisect" -s "h=np.sort(np.random.uniform(size=10000))" -s "n=np.sort(np.random.uniform(size=1000))" "r=[bisect.bisect_left(h,i) for i in n]"

200 loops, best of 5: 1.61 msec per loop

2. Shortened search in for loop

This was the solution kindly provided by @lenik

python3 -m timeit -s "import numpy as np" -s "import bisect" -s "h=np.sort(np.random.uniform(size=10000))" -s "n=np.sort(np.random.uniform(size=1000))" "r=[bisect.bisect_left(h,n[0])]" "for i in n[1:]:" "    r.append(bisect.bisect_left(h,i,r[-1]))"

200 loops, best of 5: 1.6 msec per loop

Hardly different from the list comprehension which I was somewhat surprised about...

3. Numpy searchsorted

python3 -m timeit -s "import numpy as np" -s "import bisect" -s "h=np.sort(np.random.uniform(size=10000))" -s "n=np.sort(np.random.uniform(size=1000))" "r=np.searchsorted(h,n)"

10000 loops, best of 5: 33.6 usec per loop

Approximately 50 times faster than the list comprehension based solutions for this example, so hands down the fastest.

First pandas DataFrame column index greater than x

You want to check both if any value in the dataframe is greater than the given value, and also return the first value that satsfies the condition. You have idxmax for that:

def first_greater(df, n, col):
m = df.col.ge(n)
return m.any() and m.idxmax()

Note that in the return statement, the right part of the and is only evaluated if the first condition m.any() is satisfied, otherwise False is returned.


Let's check with the proposed examples:

first_greater(df, 5, 'col1')
# 0

first_greater(df, 7, 'col1')
# 5

first_greater(df, 4, 'col1')
# 2

first_greater(df, 6, 'col1')
# 2

first_greater(df, 22, 'col1')
# False

Input data -

    col1
0 1
1 -5
2 6
3 4
4 -7
5 12
6 -2
7 0
8 -3

Counting the pairs in a list such that their first index is less than the second but the first element is greater than the second

Mergesort should be able to do this in O(nlogn).
During the merge process, when we have to merge the left and the right array, we compare the first elements of both the arrays, if first element of the right array is less than the current first array of the left array, pop it, add it to a new temp array. Also increment the counter by the length of the left array (since all the elements in the left array are greater but have a smaller index).

def mergeSort(a):
if len(a) >= 2:
mid = len(a)//2
left, right = mergeSort(a[:mid]), mergeSort(a[mid:])
temp = []
i, j = 0, 0
for _ in range(len(a)):
if i < len(left) and j < len(right):
if right[j] < left[i]:
temp.append(right[j])
# here we are counting are our pairs
counter[0] += len(left)-i
j += 1
else:
temp.append(left[i])
i += 1
elif i < len(left):
temp.append(left[i])
i += 1
else:
temp.append(right[j])
j += 1
return temp
else:
return a

counter = [0]
arr = [5, 2, 10, 9, 7]
mergeSort(arr)
print(counter[0])



Related Topics



Leave a reply



Submit