0

Please is there a faster way to find out if a number is between two numbers. My current code is below. Thanks

lists = [2.3, 4, 3,5.5, 6.5, 7.5, 6, 8]
newlist = []
a = 2
b = 7
for i in lists:
    if min(a, b) < i < max(a, b):
        newlist.append(i)
print(newlist)
  • 1
    How have you determined that this is too slow? You could calculate the `min` and `max` outside the loop, but that will be a pretty small improvement. Also, if the list is always sorted, you can exit early. – Mark May 18 '21 at 19:10
  • 1
    This should be pretty good already – Lucas Ng May 18 '21 at 19:10
  • 1
    I think this is already the fastest code ever written in Python. – enzo May 18 '21 at 19:10
  • Thanks. I believe it is fast enough too. Just checking. Thanks for your help. – Naheem Olaniyan May 18 '21 at 19:11
  • 1
    `a` and `b` don't change, so you don't need to repeatedly call `min` and `max` inside the loop. Just put `if b < a: a, b = b, a` before the loop; then `if a < i < b` will suffice inside. – chepner May 18 '21 at 19:12
  • why don't you first take out `min`, `max` values instead of using it inside loop at each iteration? `minValue,maxValue = min(a,b), max(a,b)` ` – ThePyGuy May 18 '21 at 19:12
  • Just finding out the maximum and minimum everytime inside the loop, just take those two functions outside the loop. – Exotic Cut 5276 May 18 '21 at 19:12
  • This has been answered in https://stackoverflow.com/questions/13628791/determine-whether-integer-is-between-two-other-integers – alexfoo May 18 '21 at 19:13
  • You might be able to improve it if the list is sorted. – Yoshikage Kira May 18 '21 at 19:13
  • Do you know ahead of time if `lists` is sorted? If so, you can stop the iteration early once `i` is greater than the maximum. You can also use binary search to find the first item greater than the minimum. Whether these would be worthwhile optimizations depends on how long the list is, though. – chepner May 18 '21 at 19:14

3 Answers3

2
lists = [2.3, 4, 3,5.5, 6.5, 7.5, 6, 8]
newlist = []
a = 2
b = 7
minimum = min(a, b)
maximum = max(a, b)
for i in lists:
    if minimum < i < maximum:
        newlist.append(i)
print(newlist)

This will make things faster as we are not computing minimum and maximum everytime when the loop runs and conditions are checked.

Exotic Cut 5276
  • 235
  • 4
  • 18
2

Try the following:

a, b = min(a, b), max(a, b)
newlist = [x for x in lists if a < x < b]

With 100000 iterations, I found it 3 times faster than the original code. Using list comprehension instead of if helps a little, but most improvements come from pre-defining max and min before list comprehension (or if);

  • 0.1944 sec.: list comprehension + min & max predefined
  • 0.2672 sec.: if + min & max predefined
  • 0.5600 sec.: original (if + min & max at each iteration)
j1-lee
  • 13,764
  • 3
  • 14
  • 26
0

When looking for where your code is slow, profile built-in module is handy. Here we can use it following way

import cProfile as profile
def func():
    lists = [2.3, 4, 3,5.5, 6.5, 7.5, 6, 8]
    newlist = []
    a = 2
    b = 7
    for i in lists:
        if min(a, b) < i < max(a, b):
            newlist.append(i)
    print(newlist)
profile.run('func()')

output is

[2.3, 4, 3, 5.5, 6.5, 6]
         27 function calls in 0.000 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 <stdin>:1(func)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {built-in method builtins.exec}
        8    0.000    0.000    0.000    0.000 {built-in method builtins.max}
        8    0.000    0.000    0.000    0.000 {built-in method builtins.min}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.print}
        6    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

As you might deduce max and min was used 8 times each but in this case once for min and once for max would be enough. Sample data is too tiny to say anything useful about time of execution of components. If you wish you might use more data (longer lists) and look for results.

Daweo
  • 31,313
  • 3
  • 12
  • 25