0

I have a large list which I put in a file without any line break:

puts $output_file ", [format " %s" [join $elems ","]]"

however I need to insert a line break every 8 elements, since the resulting file is not interpreted correctly.

I wonder if there is some kind of built in function to do that?

If not I was thinking about a procedure returning a string with line breaks or a function writing to file every 8 elements.

anyone had the same problem?

Is there something like this in TCL : How do you split a list into evenly sized chunks?

thanks.

Community
  • 1
  • 1
user1616685
  • 1,310
  • 1
  • 15
  • 36

2 Answers2

2

You can use the lrange command to get the required range of list elements and loop it through till the end.

set input {1 2 3 4 5 6 7 8 9 10 11 12} 
for {set startIdx 0} {$startIdx<[llength $input]} {incr startIdx 8} {
    set endIdx [expr {$startIdx+7}]
    puts [lrange $input $startIdx $endIdx]
}

Output :

1 2 3 4 5 6 7 8
9 10 11 12

Even if the endIdx exceeds the actual size of the list, it is not an issue. This is the reason, when the loop runs for the second time, the endIdx will be 15 and Tcl will return list elements only up to 11th index element.

Dinesh
  • 16,014
  • 23
  • 80
  • 122
2

One way to do it is to define a command that, when run as a coroutine, will return parts ("chunks") of a list, one at a time. This command takes a list, a length, and an optional starting index (default 0). When it has exhausted the list, it returns an empty list forever.

proc chunk {list n {i 0}} {
    yield
    set m [expr {$n - 1}]
    while 1 {
        yield [lrange $list $i $i+$m]
        incr i $n
    }
}

Create the coroutine command, providing the list and the length:

coroutine nextchunk chunk $input 8

Use it like this:

for {set chunk [nextchunk]} {[llength $chunk] > 0} {set chunk [nextchunk]} {
    puts [join $chunk ", "]
}

Documentation: coroutine, expr, for, incr, join, llength, lrange, proc, puts, set, while, yield

Peter Lewerin
  • 13,140
  • 1
  • 24
  • 27
  • 1
    Nice solution, but I saw this error message: `invoked "break" outside of a loop` – glenn jackman May 10 '16 at 14:42
  • 1
    @glennjackman: it worked for me in `tkcon` because it meddles with the exceptions. In other shells, that error message appears. A reminder to always test code in different shells... I've posted an alternative solution that works in all three shells. – Peter Lewerin May 10 '16 at 16:01