1

Is there a better way to compare variables if they can be NaN? Surely there must be something built-in for this, right?

NaN = float("NaN")

def remove(obj, value_1):
    for key in reversed([
            i for i, value_2 in
            enumerate(obj) if
            value_1 != value_1 and
            value_2 != value_2 or
            value_1 == value_2]):
        del obj[key]
    return obj

def test(value_1, value_2):
    assert (
        value_1 != value_1 and
        value_2 != value_2 or
        value_1 == value_2)

print(remove([0, NaN], NaN))
test(NaN, NaN)

Output:

[0]
# No assertion error

I'm writing a JSON patcher and I want to be be able to remove NaN values from a list with an operation or raise an error if a value is not equal to NaN, I don't think the normal behaviour is particularly useful here. The full code is a bit too much to share here I'm afraid.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Nineteendo
  • 882
  • 3
  • 18
  • 1
    So, you want `NaN` to compare *equal*? – juanpa.arrivillaga Dec 23 '22 at 07:34
  • Yes, I I want to be able to remove them from a list or catch an error is a value is not NaN. – Nineteendo Dec 23 '22 at 07:35
  • Sorry, what exactly are you trying to do? Because if you just want to remove them from a list, something like `[x for x in mylist if not math.isnan(x)]` – juanpa.arrivillaga Dec 23 '22 at 07:39
  • 2
    " and I want to be be able to remove NaN values from a list with an operation or raise an error if a value is not equal to NaN" Then it seems like you just want `math.isnan` – juanpa.arrivillaga Dec 23 '22 at 07:44
  • Ok, added how it would be used, but please note that isnan trows an error when you don't check a number. – Nineteendo Dec 23 '22 at 07:46
  • I mean, then you could just use the idiom `val != val`, which wouldn't throw an error in that case, both otherwise, you could use `isinstnace(x, float) and math.isnan(x)` – juanpa.arrivillaga Dec 23 '22 at 08:11
  • I'm not following the question. Please show a real example of a list or a few lists you'd want to filter, and the output you want. – wjandrea Dec 23 '22 at 17:23
  • @wjandrea, I've adapted my code to make it closer to what I'm using. – Nineteendo Dec 24 '22 at 17:39
  • 1
    Did you try wrapping the comparison logic into its own function and calling that everywhere it's needed? It's not really clear what else you could be asking for here. `==` is special-cased for `NaN` **following the IEEE-754 standard, specifically so that** `NaN` can be easily detected without library functions. If you want it to work differently, you'll need to use a bit of logic, along the lines of what you already have, to patch around it. – Karl Knechtel Dec 24 '22 at 17:43
  • @Nineteendo What do you mean by "raise an error if a value is not equal to NaN"? Are you talking about the assertion? At first I thought you meant that, while removing from the list, if you try to compare NaN with something, then raise an error. BTW, check out [ask] for tips on how to write a good title. – wjandrea Dec 24 '22 at 20:39
  • BTW, [making in-place operations return the object is a bad idea](/q/13062423/4518341). Either way, a list comp would be easier than that for-loop. – wjandrea Dec 24 '22 at 20:40
  • Yeah, @KarlKnechtel, I think that writing a function for this would make my code more readable. (And all weird logic would be at the same place) – Nineteendo Dec 24 '22 at 21:39
  • OK, @wjandrea, it's a validation check to check if data has the correct value, and I also wanted to allow checking for NaN. I tried to make the code more specific, but I'm afraid I might need to share the whole code (400 lines) to explain why I'm working like this. – Nineteendo Dec 24 '22 at 21:42

1 Answers1

0

You can use this logic for comparision:

x = float("NaN")
y = float(1)
print(x!=x) # True
print(y!=y) # False

If you check for not equals (!=) for a nan type. It always returns true, because they are generated as invalid float operators.