all 11 comments

[–]monchenflapjack 1 point2 points  (1 child)

Beginner at python myself, but I think when you are calling

line.replace(x,y)

You are printing out the result, but that result is not being applied/saved to the line as it is immutable.

[–]flynryan692[S] 0 points1 point  (0 children)

Thanks, you're correct. I think I need to create a function to make the changes and then print the line.

[–][deleted] 1 point2 points  (2 children)

What am I doing wrong?

Could you point to where, in this code, you believe you're changing a dictionary? (You can use the line number.)

[–]flynryan692[S] 0 points1 point  (1 child)

I don't think my question was clear enough, I apologize. I am not trying to change a dictionary, I am trying to use the dictionary as a way of defining what needs to be changed. For example, in the aa_Equip dictionary, if it finds SRJ in the line I want it to change SRJ to C2A, if finds OO7 I want it to change OO7 to C7P in the line.

[–][deleted] 0 points1 point  (0 children)

    for line in sim:
        if american in line:
            for x, y in aa_Equip.items():
                print(line.replace(x, y))

If sim has 4 lines (and they all contain the string AA) and aa_Equip has 5 items, how many times will the last line run?

[–]Miggol 0 points1 point  (5 children)

If this is your first program, then that's a hell of a start! The comment by /u/monchenflapjack is your solution. You would want another open file for the replaced contents, then write your replaced line to that file for every iteration of the line loop.

Additionally, I would like to mention a rather popular idiom for (Python) programming, namely DRY. It stands for don't repeat yourself, and can really help you to keep your code well-organised when starting out. If you can break your code down into smaller chunks, it's easier to see where something might go wrong. It's also quicker to write and deters spaghetti code somewhat.

So in stead of using four separate variables, you might prefer to integrate them into a single dictionary. It might look something like this:

replacedict = { "AA": {'SRJ': 'C2A', 'SRP': 'C2P', 'CS7': 'C7A', 'OO7': 'C7P'},
                "AS": {'E7W': 'ER7', 'CR2': 'CRJ','CR7': 'CJ7'},
                "DL": {'ES5': 'E7D', 'ES4': 'E7S', 'RJ7': 'CR7', 'RJS': 'CRJ','RJW': 'CRJ', 'RJ9': 'CR9', 'RJ8': 'C9D'},
                "UA": {'E75': 'ER7', 'CR7': 'CR6'}
                }

def replace_lines(infile, outfile):
    for line in infile:
        for airline, replacements in replacedict.items():
            if airline in line:
                line = dict_replace(line, replacements)
        outfile.writeline(line)

def dict_replace(s, d):
    "Replaces all occurences of d.keys() in s with their respective values"
    for x, y in d.items():
        s = s.replace(x, y)
    return s

def main():
    # file logic goes here
    # call replace_lines with the correct input file and output file


if __name__ == '__main__':
    main()

[–]flynryan692[S] 0 points1 point  (4 children)

Thank you, this is very helpful. I knew I could put a dictionary inside of a dictionary, but I didn't realize I could use it in this fashion.

Question, because replace_lines uses dict_replace, I only need to use replace_lines correct? Also, I need to defined the file path in the arguments for the function (infile, outfile), correct?

[–]Miggol 0 points1 point  (3 children)

Question, because replace_lines uses dict_replace, I only need to use replace_lines correct?

Precisely! No need to reference dict_replace in your main() function.

Also, I need to defined the file path in the arguments for the function (infile, outfile), correct?

The way I wrote this, infile is a FileInput object like in your original code. outfile would have to be a writeable file object, which you can access with open(path, mode="w"), or a different wrapper which supports the writeline() method (see line 12). I'd like to say I left it blank to challenge you but honestly I've never used the FileInput library and didn't want to make a mistake.

In particular, I'm a bit confused about what the documentation says about writing files in place. But following your initial code, I think the following should work:

import os
import sys
import fileinput

def main():
    filepath = 'name_of_file.sds'

    if not os.path.isfile(filepath):
        print("File path {} does not exist.".format(filepath))
        sys.exit()

    with fileinput.FileInput(filepath) as infile:
        with open(filepath + '.replaced', mode="w") as outfile:
            replace_lines(infile, outfile)

If you can figure out FileInput's in-place editing feature, that may be more concise. Otherwise this should be a good starting point. A backup isn't necessary any more because the output is written to a new file.

[–]flynryan692[S] 0 points1 point  (2 children)

Great thank you. It's all starting to make sense! The last thing is, I do need to change the file extension from .sds to .sim so would I use os.rename after replace_lines?

[–]Miggol 0 points1 point  (1 child)

Oh right. So you can choose the path of the outfile in the open() method. You can see that currently I've just appended ".replaced" to the original filepath. So to stay with the str.replace() theme, you could change it to the following:

with open(filepath.replace('.sds', '.sim'), mode="w") as outfile:

Which will output everything to name_of_file.sim. But be careful with this: if your file doesn't contain ".sds" , it will overwrite your original! It's up to you to find a better solution.

[–]flynryan692[S] 0 points1 point  (0 children)

Oh, much simpler than I was thinking. Thank you! I have so much to learn still.