[Tutor] Setting thresholds in a compact way

Martin A. Brown martin at linux-ip.net
Wed Jan 1 22:25:49 EST 2020


Hello there,

>First of all let me wish a great 2020 for all of you kind souls and seekers
>of knowledge :)
>
>I am trying to setup a varying time.sleep value (in house) depending on a
>priorly determined threshold.
>
>If threshold <= .9 AND > .8 then sleep should be 6 hours
>if threshold <= 0.8 AND > .4 then sleep should be 4 hours
>if threshold <= .4 AND > .1 then sleep should be 3 hours
>if threshold <= .1 then sleep should be set to 1 hour
>
>Instead of a complex/lengthy series of (nested?) if/ands based on the
>above, I was wondering if I could declare a dictionary such as:
>
>sleep_thresholds_hours = {.9:6, .8:4, .4:3, .1:1}
>
>And then use some sort of single statement to set the sleep_time to the the
>proper value.

I saw the thread here and thought I'd spend a few minutes writing a few
functions that I think you might find helpful.

I like the suggestion Mats had about multiplying (or using some other
mathematical function) based on the input value.  But, that may not work in
your case.

I don't know how to apply the sparse array solution, suggested by Alan.

Here is an example or two, of possible utility.  If you are simply testing
ranges, you can always cover the search space in order (I start from the
"bottom"):

  def series_of_ifs(val):
      assert val == abs(val)  # -- ineffably positive
      if val <= 0.0: return None
      if val <= 0.1: return 1
      if val <= 0.4: return 3
      if val <= 0.8: return 4
      if val <= 0.9: return 6
      return None

  def data_driven_dict(val):
      assert val == abs(val)  # -- ineffably positive
      thresholds = [(0, None),
                    (0.1, 1),
                    (0.4, 3),
                    (0.8, 4),
                    (0.9, 6)
                    ]
      for threshold, result in thresholds:
          if val <= threshold:
              return result
      return None

Attached is a small script with these functions and a little testing 
code around them, that should allow you to test other ways of 
writing what you want.

If I knew I would want to monkey with the thresholds later, I'd use 
the data_driven_dict() solution.

Oh, and I didn't know what you wanted to do with values above 0.9, 
so I just chose to "return None" for those.  Also, given your sample 
data, I sort of assumed that your data were in the range of [0, 1), 
but if they are not, you may need to handle negative, as well.  I 
chose to assert, effectively terminating the program if the value is 
negative.

>Not even quite sure that using floats (albeit single decimal) as dictionary
>keys will be ok.

Yep!  This will be quite OK.  This may be a bit odd, but from a 
Python interpreter, I used something as a key, and then, for no 
specific reason, I assigned the value to the type of that value.  
Which had the amusing side effect that after I was done, I could 
write a little loop to assert that the key (retrieved in a loop) was 
actually of the type indicated.

  >>> d = dict()
  >>> d[17] = int
  >>> d[0.2] = float
  >>> d['hedgehog'] = str
  >>> d[('a', 'b', 7)] = tuple
  >>> d
  {17: <type 'int'>, ('a', 'b', 7): <type 'tuple'>, 0.2: <type 'float'>, 'hedgehog': <type 'str'>}
  >>> for k, v in d.items():
  ...     assert type(k) is v
  ... 
  >>> 

Best of luck,

-Martin

-- 
Martin A. Brown
http://linux-ip.net/


More information about the Tutor mailing list