Home > Mobile >  How do I move the contents of a .txt file to a dictionary in TCL?
How do I move the contents of a .txt file to a dictionary in TCL?

Time:11-12

Pretty rusty at tcl so bear with me if the solution to this questions is a fairly simple one.

I have a .txt file that contains sites and addresses with one space between them. It looks something like this:

site1 address1
site2 address2
site3 address3
.
.
.
.

I want to read the .txt file and create a dictionary with sites as keys and values as addresses in tcl. So my result tcl dictionary should look something like this:

dict = {"site1": "address1", "site2": "address2", ........}

How do I do this in tcl?

I only have an idea on how to implement this in Python but no clue whatsoever in tcl.

CodePudding user response:

I have a .txt file that contains sites and addresses with one space between them.

As long as there aren't other spaces besides the ones separating the key and value strings, you just have to read the entire file in as a string and start treating it as a dict:

#!/usr/bin/env tclsh

set fp [open input.txt]
set mydict [read $fp]
close $fp
puts [dict get $mydict site3] ;# address3

CodePudding user response:

It depends on what the actual formats of the site1 and address1 (etc.) are. As written, you already have a dictionary, but that only remains necessarily true as long as the keys and values are simple values. That would be true still if the real addresses were, say, memory addresses, but wouldn't be true if they were postal addresses, as those contain spaces.

Once you have a format that contains spaces, you're better off using regexp to do the parsing. Fortunately, that's relatively easy:

# Standard stanza for reading a file
set f [open input.txt]
set data [read $f]
close $f

# Use the foreach to drop the matched lines; we just want the parts of them
foreach {- k v} [regexp -all -inline -line {^(\w )\s(. )$} $data] {
    # Trim the whitespace from the value; that's usually the right thing to do
    dict set mydict $k [string trim $v]
}

The -line option makes the RE only match within a line; it's great for this sort of data as it means we don't need a separate split $data \n. Without it, we'd need:

foreach line [split $data \n] {
    if {[regexp {^(\w )\s(. )$} $data -> k v]} {
        dict set mydict $k [string trim $v]
    }
}

That works, but it's usually a better plan to hoist as much work into command implementations as possible.

  • Related