4

I have a list of List of Tuples (string, float) with float('nan'). How can i get the tuple with the smallest number? If I use min I always get the nan.

[('GroundBasedMechWT', nan), ('GroundBasedCTL', nan), ('GroundBasedManualWT', nan), ('GroundBasedManualLog', nan), ('CableManualWTLog', 60.77), ('CableManualWT', 58.52), ('CableManualLog', 68.17), ('CableManualCTL', nan), ('HelicopterManualWT', 96.82), ('HelicopterManualCTL', nan)]
ustroetz
  • 5,802
  • 16
  • 47
  • 74

4 Answers4

3

You can use a custom key, that will return a very high value for NaN:

min(list, key=lambda x: float('inf') if math.isnan(x[1]) else x[1])
mgibsonbr
  • 21,755
  • 7
  • 70
  • 112
  • 1
    your syntax is wrong -- it should be `key=lambda x: ...` and this won't work as `float('nan') == float('nan')` will never be `True`. (Thank the IEEE committee for that one!) – mgilson Mar 01 '13 at 01:11
  • well then I could also substitute my NaN wit inf. I will still not get the min number in return. – ustroetz Mar 01 '13 at 01:13
  • Yep. I see. That should work. +1. I knew there had to be an `isnan` floating around somewhere (pun intended) – mgilson Mar 01 '13 at 01:13
1

You could also try this:

min(filter(lambda t: not math.isnan(t[1]), l), key=itemgetter(1))

where itemgetter refers to operator.itemgetter.

arshajii
  • 127,459
  • 24
  • 238
  • 287
0
>>> nan=float('NaN')
>>> x=[('GroundBasedMechWT', nan), ('GroundBasedCTL', nan), ('GroundBasedManualWT', nan), ('GroundBasedManualLog', nan), ('CableManualWTLog', 60.77), ('CableManualWT', 58.52), ('CableManualLog', 68.17), ('CableManualCTL', nan), ('HelicopterManualWT', 96.82), ('HelicopterManualCTL', nan)]
>>> nan<1
False
>>> nan<1.0
False
>>> min(x)
('CableManualCTL', nan)

I don't think nan is considered smaller than regular floats. Probably min is comparing the strings alphabetically.

(Not a complete answer, but might help)

Emilio M Bumachar
  • 2,532
  • 3
  • 26
  • 30
  • I don't think this should be an answer (maybe a comment instead). – arshajii Mar 01 '13 at 01:24
  • Try `1 < nan` and `1.0 < nan`, and you'll get the same result (`False`). Even `nan == nan` should return `False`. But you're right in that, if comparing tuples using the default comparator, it will first sort the first element alphabetically, then use the second if two have the same first element. – mgibsonbr Mar 01 '13 at 01:28
  • @A.R.S.: I fear I just couldn't express it as clearly without a fair bit of code – Emilio M Bumachar Mar 01 '13 at 01:34
0
nan=float('NaN')
x=[('GroundBasedMechWT', nan), ('GroundBasedCTL', nan), ('GroundBasedManualWT', nan), ('GroundBasedManualLog', nan), ('CableManualWTLog', 60.77), ('CableManualWT', 58.52), ('CableManualLog', 68.17), ('CableManualCTL', nan), ('HelicopterManualWT', 96.82), ('HelicopterManualCTL', nan)]
val=('foo', float('Inf')) #thanks for teaching me that
for tup in x:
    if tup[1]<val[1]:
        val=tup
print val

Fails on the empty list, but otherwise solves the problem.

Emilio M Bumachar
  • 2,532
  • 3
  • 26
  • 30