0

I have two lists

a = [1, 4, 12]
b = [2, 13]

I want to know if values in list b are between two values in list a So, in this case, 2 will fall between 1 and 4. 13 will not fall between any numbers.

I have tried bisect function, but I couldn't get it work. I was able to use it with a single value and a list, but not two lists.

Yun Tae Hwang
  • 1,249
  • 3
  • 18
  • 30
  • In the case above, do you want the output to be [True, False] – Sid Kwakkel Nov 11 '20 at 17:28
  • Between _any_ two numbers, or between numbers that occur after each other, or _directly_ after each other? Is the first list sorted? And do you seek only yes/no, or the actual numbers and/or their position in the list? Should _all_ the values in `b` lie between the same numbers from `a`, or are they independent? – tobias_k Nov 11 '20 at 17:31
  • @SidKwakkel yes True, False will work – Yun Tae Hwang Nov 11 '20 at 17:35
  • @tobias_k two lists are independent - there might be no value fall between two numbers. Also, suppose the two lists are sorted. – Yun Tae Hwang Nov 11 '20 at 17:36
  • Also, does "between" mean that the numbers have to be strictly smaller and lesser than the ones they are "between"? And what about the boundaries? Would `1`, `4` and `12` be "between" any numbers of `a`? – tobias_k Nov 11 '20 at 17:59

4 Answers4

4

Maybe there's some subtlety that I do not get, but unless I am mistaken, you only have to check whether the elements are between the min and max from a. This is independent of whether the elements in a are sorted, or whether the values from b have to be between consecutive values from a. As long as they are between the min and max, there has to be a "segment" in a those values are in.

>>> a = [1, 4, 12]
>>> b = [2, 13]
>>> n, m = min(a), max(a)
>>> [n < x < m for x in b]
[True, False]

That is, of course, only if (a) you do not need which numbers they are in between, and (b) if not all values in b have to be in the same interval.

If you think I missed something, please comment.

tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • wait, that's correct! how did we miss that. Also the `(a)` point you listed isn't really a downside. Should work with `[x for x in b if n < x < m]` anyway. – Chase Nov 11 '20 at 17:47
  • One possible caveat: If "between" really means `n < x < m`, then there might not be any interval the numbers from `b` are "in between" if list `a` is "dense", e.g. `3` not being between any numbers in `[1,2,3,4,5]`. – tobias_k Nov 11 '20 at 17:57
  • l am supposing that a and be will never have the same number. if 3 is in list A then B will never contain 3 – Yun Tae Hwang Nov 11 '20 at 18:46
2

It really depends on what you want it to return. I wrote a code that will return the first pattern that it finds, but with some changes I'm sure it would not be difficult to return all combinations.

def get_between(a, b):
    a, b = sorted(a), sorted(b)
    
    for b_value in b:
        smaller = None
        greater = None
        for a_value in a:
            if b_value > a_value:
                smaller = a_value
            elif b_value < a_value:
                greater = a_value
            
            if smaller and greater:
                return f"{b_value} is between {smaller} and {greater}"
    
    return "There is no such combination"

a = [1, 4, 12]
b = [2, 13]
print(get_between(a, b))

The output on that case will be 2 is between 1 and 4, but you can adapt the return value to be whatever you want.

Mateus
  • 266
  • 1
  • 7
1

You can keep two running indices to get a list of all elements that fall between values:

def get_between(arr1, arr2):
    # first sort the arrays
    arr1 = sorted(arr1)
    arr2 = sorted(arr2)
    # keep two indices into them
    i1 = 0
    i2 = 0
    # keep track of the values between two values
    ret = []
    while i1 < len(arr1) - 1 and i2 < len(arr2):
        # we're too small to be between a value
        # so we should increase the second index
        if arr2[i2] < arr1[i1]:
            i2 += 1
        # we're too large to be between a value
        # so we should increase the first index
        elif arr2[i2] > arr1[i1 + 1]:
            i1 += 1
        # we are between a value
        # so we should append to the return array
        # and move on to the next element
        else:
            ret.append(arr2[i2])
            i2 += 1
    return ret

get_between([1, 4, 12], [2, 8, 13]) # [2, 8]
Aplet123
  • 33,825
  • 1
  • 29
  • 55
1

If you don't care much about performance, here's a pythonic solution-

def betwn(rangelist, valuelist):
    # Get list of all ranges between each consecutive number of rangelist
    rgs = [range(rangelist[n], rangelist[n + 1]) for n in range(len(rangelist) - 1)]
    # A function to check whether a given element exists between 2 consecutive numbers of rangelist
    verifyfunc = lambda e: any(e in r for r in rgs)
    # Return the qualifying elements from valuelist
    return [e for e in valuelist if verifyfunc(e)]

Output

>>> betwn([1, 4, 12], [2, 13])
[2]
Chase
  • 5,315
  • 2
  • 15
  • 41