Wessowang
Wessowang

Reputation: 61

Replace floats with ints in text files

I want to find and replace floats with integers in several text files.
There is one float value per text file which I want to convert. It is always after a specific keyword and has to be multiplied by 10.000.
e.g. the float 1.5 should be turned into the integer 15.000
The other floats after 1.5 don't have to be changed though

def edit(file):
    with open(file, 'r') as f:
        filedata = f.read()
        for line in filedata:
           if "keyword" in line:
              filedata = filedata.replace(re.search(r"\d+\.\d+", line).group(), str(10000*re.search(r"\d+\.\d+", line).group()))
    with open(file, 'w') as f:
        f.write(filedata)

I was trying to replace the the float using a regex. But this doesn't work

EXAMPLE FILE EXTRACT

abcdef 178 211 208 220    
ghijkl 0 0 0 0  
keyword 1.50 1.63 1.56 1.45

Upvotes: 2

Views: 498

Answers (2)

Phoenixo
Phoenixo

Reputation: 2123

You can iterate over lines with lines = filedata.split("\n"). Be careful because filedata is a big string containing the whole file. When you did for line in filedata, you iterated over every character of the file...

I also used another way (without regex) to find numbers and change them.

def edit(file):
    with open(file, "r") as f:
        filedata = f.read()
        lines = filedata.split("\n") # list of lines
        for index, line in enumerate(lines):
            if "keyword" in line:
                words = line.split() # ['keyword', '1.50', '1.63', '1.56', '1.45']
                for i, w in enumerate(words):
                    try:
                        # transform number to float, multiply by 10000
                        # then transform to integer, then back to string
                        new_word = str(int(float(w)*10000))
                        words[i] = new_word
                    except:
                        pass
                lines[index] = " ".join(words)
        new_data = "\n".join(lines) # store new data to overwrite file


    with open(file, "w") as f: # open file with write permission
        f.write(new_data) # overwrite the file with our modified data

edit("myfile.txt")

Output :

# myfile.txt
abcdef 178 211 208 220    
ghijkl 0 0 0 0  
keyword 15000 16299 15600 14500

EDIT : More Compact way

def edit(file):
    with open(file, "r") as f:
        filedata = f.read()
        line = [x for x in filedata.split("\n") if "keyword" in x][0]
        new_line = line
        for word in line.split():
            try: new_line = new_line.replace(word, str(int(float(word)*10000)))
            except: pass
    with open(file, "w") as f: # open file with write permission
        f.write(filedata.replace(line, new_line)) # overwrite the file with our modified data

edit("myfile.txt")

Upvotes: 1

Serge Ballesta
Serge Ballesta

Reputation: 149025

When you find yourself using a regex inside a loop, you should compile it ouside of the loop.

Next, if you want to replace a value in a line, you should not search for it in the whole file.

Finally you must cast a string to a numeric type to operate on it. If you do not you will just repeat the string ('10' * 2 is '1010' not 20 nor '20')

Here is a possible improvement of your code:

def edit(file):
    with open(file, 'r') as f:
        rx = re.compile(r"\d+\.\d+")        # compile the regex only once
        filedata = f.readlines()            # get a list of the lines of the file
        for i, line in enumerate(filedata): # and enumerate them
            if "keyword" in line:
                val = re.search(r"\d+\.\d+", line).group()   # split the complex line
                newval = str(int(float(val) * 10000))
                filedata[i] = line.replace(val, newval)      # replace only the current line
                break                                        # no need to proceed further
    with open(file, 'w') as f:
        f.write(filedata)

Upvotes: 1

Related Questions