简体   繁体   中英

Negative values in a certain range

Given a list:

a = [-20,-15,-10,-5,0]

and another:

b = [-3,-10,-14,-19,-13,-5,-0.5]

I now want a result dictionary that looks like the following:

N = {'-20 to -15': [-19], '-15 to -10': [-14,-13,-10], '-10 to -5': [-3,-5], '-5 to 0': [-0.5]} 

The problem now is that I already can't get the "range" check correct. Can someone help me with the error in the code? I tried to get the index via a while loop:

j=0
while j < len(a):
   index1 = next(x[0] for x in enumerate(b) if x[1] >= a[j])          
   index2 = next(x[0] for x in enumerate(b) if x[1] < a[j+1])
   j=+1

There seems to be a problem somehow with comparing the negative values, at least I think. I would be very grateful for help!

A list comprehension inside a dictionary comprehension should do it:

>>> {f"{i} to {j}": [x for x in b if i < x <= j] for i, j in list(zip(a, a[1:]))}
{'-20 to -15': [-19], '-15 to -10': [-10, -14, -13], '-10 to -5': [-10, -5], '-5 to 0': [-3, -5, -0.5]}

Explanation:

  • list(zip(a, a[1:])) : generates the ranges as a list of tuples
  • [x for x in b if i <= x <= j] : generates a list of values inside a given range
  • f"{i} to {j}" : Formats the dictionary key

Your code example is not going to produce the result you are expecting at all. I am afraid, you are not aware of what is a product of function you are using ( next and enumerate ).

But here is simple code to produce the expected result:

a = [-20,-15,-10,-5,0]
b = [-3,-10,-14,-19,-13,-5,-0.5]

result = {}

for index, value in enumerate(a[:-1]):
    key = f"{value} to {a[index+1]}"
    result_value = [x for x in b if x >= value and x <= a[index+1]]
    result[key] = result_value

print(result)

This will give you lists in ranges:

a = [-20,-15,-10,-5,0]
b = [-3,-10,-14,-19,-13,-5,-0.5]
interval = range(0, -25, -5)

for i in range(len(interval) - 1):

    lower = interval[i+1]
    higher = interval[i]

    print ([x for x in a if x >= lower and x < higher])
    print ([x for x in b if x >= lower and x < higher])

You just have to apply some formatting.

You can do this with a single dictionary and list comprehension. You can create the dictionary you want to use and in it loop over b to include the values you want.

In order to do this you would also need a list of low and high values you want. By offsetting a and zipping it with itself you create that list.

{f'{low} to {high}':[num for num in b if (num>low and num<=high)] for low, high in zip(a, a[1:])}

The code below works pretty straightforward. It gives the required output.

a = [-20,-15,-10,-5,0]
b = [-3,-10,-14,-19,-13,-5,-0.5]
a = sorted(a)
b = sorted(b)
out = {}
for i in range(len(a)-1):
    first = a[i]
    last = a[i+1]
    key = "{} to {}".format(first, last)
    out[key] = []
    for j in b:
        if j >= first and j <= last:
            out[key].append(j)
print(out)

Others have proposed quadratic approaches, but this can be done in log-linear time (for simplicity, I autogenerated the bounds using floor division by 5):

from itertools import groupby

result = {}
for k, g in groupby(sorted(b), key=lambda n: (n-1)//5):
    result[f"{5*(k)} to {5*(k+1)}"] = [*g]

result
# {'-20 to -15': [-19], '-15 to -10': [-14, -13, -10], 
#  '-10 to -5': [-5], '-5 to 0': [-3, -0.5]}

You can use a helper function similar to the pairwise() itertools recipe and a dictionary comprehension to do it like this:

def pairwise(iterable):
    """s -> (s0,s1), (s1,s2), (s2, s3), ..."""
    a, b = iter(iterable), iter(iterable)
    next(b, None)
    return zip(a, b)

a = [-20,-15,-10,-5,0]
b = [-3,-10,-14,-19,-13,-5,-0.5]
b = sorted(b)
n = {f'{lo} to {hi}': [val for val in b if lo < val <= hi]
        for lo, hi in pairwise(a)}
print(n)

Output:

{'-20 to -15': [-19], '-15 to -10': [-14, -13, -10], '-10 to -5': [-5], '-5 to 0': [-3, -0.5]}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM