Home > Software engineering >  str.replace() can not replace zero dot (0.) to zero dot zero (0.0)
str.replace() can not replace zero dot (0.) to zero dot zero (0.0)

Time:10-03

I have an np.array called arr which is:

arr = np.array([[0.0, 0.0, 0.0], [1 / 3, 1 / 3, 0], [0.0, 0.0, 0.0]])

and I want to write its information to a single-line string called s as:

[[0.0, 0.0, 0.0], [1 / 3, 1 / 3, 0], [0.0, 0.0, 0.0]]

For this, I am using this type of conversation(in my code it is in a function):

import re
import numpy as np

arr = np.array([[0.0, 0.0, 0.0], [1 / 3, 1 / 3, 0], [0.0, 0.0, 0.0]])
s = np.array_str(arr, precision=4)
s = re.sub('(\d)  (-|\d)', r'\1,\2', s)
s.replace('^0. $', '0.0')
# s.replace('0. ', '0.0') #gives same result
s.replace('\n', ',')

print(s)

However, the result is:

[[0.     0.     0.    ]
 [0.3333,0.3333,0.    ]
 [0.     0.     0.    ]]

CodePudding user response:

You need to catch the output of s.replace() and save it as the s variable, or another variable name.

import re
import numpy as np

arr = np.array([[0.0, 0.0, 0.0], [1 / 3, 1 / 3, 0], [0.0, 0.0, 0.0]])
s = np.array_str(arr, precision=4)
s = re.sub('(\d)  (-|\d)', r'\1,\2', s)
s = s.replace('0. ', '0.0') #gives same result
s = s.replace('\n', ',')
print(s)

CodePudding user response:

You could use nested comprehensions on the array and process it using the fraction module:

from fractions import Fraction

s = "[" ", ".join("[" ", ".join(f"{Fraction(n).limit_denominator(10000)}"  
                              for n in row) "]" 
                 for row in arr ) "]"
print(s)
[[0, 0, 0], [1/3, 1/3, 0], [0, 0, 0]]

Note that, while this is close to your expected result, there is no way to distinguish the 0.0 from the 0 in the original array because this information is lost when the numbers are converted to floats by numpy. So all 0s will be printed the same way.

For more than 2 dimensions, you could generalize this into a recursive function:

from fractions import Fraction

def arrayToStr(arr):
    if isinstance(arr,np.ndarray):
        return "[" ", ".join(arrayToStr(n) for n in arr) "]"
    if not arr return "0.0"
    return f"{Fraction(arr).limit_denominator(10000)}"

This will print zeroes as 0.0 though I cannot fathom why you would want to do that specifically (and only) for zero.

Output:

arr = np.array([[0.0, 0.0, 0.0], [1 / 3, 1 / 3, 0], [0.0, 0.0, 0.0]])
print(arrayToStr(arr))
[[0.0, 0.0, 0.0], [1/3, 1/3, 0.0], [0.0, 0.0, 0.0]]

arr = np.arange(24).reshape((4,3,2))/6
print(arrayToStr(arr))
[[[0.0, 1/6], [1/3, 1/2], [2/3, 5/6]], [[1, 7/6], [4/3, 3/2], [5/3, 11/6]], [[2, 13/6], [7/3, 5/2], [8/3, 17/6]], [[3, 19/6], [10/3, 7/2], [11/3, 23/6]]]

If you don't mind getting the 1/3 values as decimals, you could use the json module which would do the formatting more directly:

import json
s = json.dumps(arr.tolist())
print(s)
[[0.0, 0.0, 0.0], [0.3333333333333333, 0.3333333333333333, 0.0], [0.0, 0.0, 0.0]]
  • Related