Casting to a "number" (both int and float)?
Jussi Piitulainen
harvesting at makes.address.invalid
Fri Aug 28 01:46:11 EDT 2015
Victor Hooi writes:
> I'm reading JSON output from an input file, and extracting values.
>
> Many of the fields are meant to be numerical, however, some fields are
> wrapped in a "floatApprox" dict, which messed with my parsing.
>
> For example:
>
> {
> "hostname": "example.com",
> "version": "3.0.5",
> "pid": {
> "floatApprox": 18403
> }
> "network": {
> "bytesIn": 123123,
> "bytesOut": {
> "floatApprox": 213123123
> }
> }
>
> The floatApprox wrapping appears to happen sporadically in the input.
>
> I'd like to find a way to deal with this robustly.
So you want a value as is when it is a number - either an int or a
float. And otherwise the value is a dict and you want the value at a
known key. Here's a literal-minded expression of the spec:
( o if isinstance(o, (int, float)) else o['floatApprox'] )
> For example, I have the following function:
>
> def strip_floatApprox_wrapping(field):
> # Extracts a integer value from a field. Workaround for the
> # float_approx wrapping.
> try:
> return int(field)
> except TypeError:
> return int(field['floatApprox'])
>
> which I can then call on each field I want to extract.
>
> However, this relies on casting to int, which will only work for ints
> - for some fields, they may actually be floats, and I'd like to
> preserve that if possible.
You could try int first, float second; you should still return the
actual value.
try:
int(field)
return field
except TypeError: pass
try:
float(field)
return field:
except TypeError:
return field['floatApprox']
There are a couple of reasons to return the actual value instead of the
result of the "cast". First, it appears to be what you want :) Second,
it allows you to have some confidence that the data actually is numeric
and not, say, strings that happen to look like numbers.
> (I know there's a isnumber() field - but you can only call that on a
> string - so if I do hit a floatApprox field, it will trigger a
> AttributeError exception, which seems a bit clunky to handle).
>
> def strip_floatApprox_wrapping(field):
> # Extracts a integer value from a field. Workaround for the
> # float_approx wrapping.
> try:
> if field.isnumeric():
> return field
> except AttributeError:
> return field['floatApprox']
I take it you haven't tried this and the fields in question actually are
numeric, not strings. That exception would be taken for a wrong reason.
You could do the following, but str.isnumeric does not do what you want.
For example, "3.14".isnumeric() is as False as "{}".isnumeric().
if str(field).isnumeric():
return field
else:
return field['floatApprox']
> Is there a way to re-write strip_floatApprox_wrapping to handle both
> ints/floats, and preserve the original format?
>
> Or is there a more elegant way to deal with the arbitrary nesting with
> floatApprox?
Consider ... if isinstance(field, (int, float)) else ... .
More information about the Python-list
mailing list