Search code examples
.netpythonf#utility

String replace utility conversion from Python to F#


I have a simple python utility code that modifies the string line by line. The code is as follows.

import re

res = ""
with open("tclscript.do","r") as f:
    lines = f.readlines()
    for l in lines:
        l = l.rstrip()
        l = l.replace("{","{{")
        l = l.replace("}","}}")
        l = re.sub(r'#(\d+)', r'{\1}',l)
        l += r'\n'
        res += l
    res = "code="+res

with open("tclscript.txt","w") as f:
    f.write(res)

How can the utility implemented with F# would look like? Can it be shorter in LOC and easier to read than this Python version?

ADDED

The python code processes tcl script in C# string. The '{'/'}' in C# string should be changed into '{{'/'}}', and number after '#' should be modified to number enclosed by '{}'. For example, #1 -> {1}.

ADDED

This is the working example

open System.IO
open System.Text.RegularExpressions

let lines = 
  File.ReadAllLines("tclscript.do")
  |> Seq.map (fun line ->
      let newLine = Regex.Replace(line.Replace("{", "{{").Replace("}", "}}"), @"#(\d+)", "{$1}") + @"\n"
      newLine )

let concatenatedLine = Seq.toArray lines |> String.concat ""
File.WriteAllText("tclscript.txt", concatenatedLine)

Or as is explained in This answer.

open System.IO
open System.Text

let lines = 
  let re = System.Text.RegularExpressions.Regex(@"#(\d+)")
  [|for line in File.ReadAllLines("tclscript.do") ->
      re.Replace(line.Replace("{", "{{").Replace("}", "}}").Trim(), "$1", 1) + @"\n"|]

let concatenatedLine = lines |> String.concat ""
File.WriteAllText("tclscript.txt", concatenatedLine)

Solution

  • I will not give you a complete example of the F# version, because I'm not sure what the regular expression in your Python version is supposed to do. However, the general structure of a nice F# solution would look something like this:

    let lines = 
      File.ReadAllLines("tclscript.do")
      |> Seq.map (fun line ->
          let newLine = line.Replace("{", "{{").Replace("}", "}}")
          // Implement additional string processing here
          newLine )
    
    File.WriteAllLines("tclscript.txt", lines)
    

    Since your snippet is working line-by-line, I used ReadAllLines to read file as a list of lines and then used Seq.map to apply a function to every line. The new collection of lines can be written to a file using WriteAllLines.

    As mentioned in the comment, I think that you can write pretty much the same thing in Python (i.e. without explicitly concatenating the string and using some higher-order function or comprehension syntax to process the collection).