Version 7 of list stripping

Updated 2002-06-04 21:48:48

ulis: If, for some syntax analyzis, you need to strip the braces of a list, here is a tiny proc that do that.

It returns "{this is} a {nested list}" for "{{{this is} a {nested list}}}". You can control the level of stripping, also.


ulis: This proc is wrong.

 [striplist {{{this is}}{{a list}}}] returns  '{this is}}{{a list}' in place of '{{this is}}{{a list}}'. 

I'm trying to publish soon a better proc.

    proc striplist {text {level -1}} \
    { 
      # expose outer braces
      set text [string trim $text]
      # while text seems braced and level is not exhausted
      while { $level != 0
           && [string index $text 0] == "\{"
           && [string index $text end] == "\}"} \
      { 
        # strip outer braces and expose inners
        set text [string trim [string range $text 1 end-1]] 
        # check if this is too much
        set n1 [string first "\{" $text]
        set n2 [string first "\}" $text]
        if {$n1 != -1 && $n2 != -1 && $n2 < $n1} \
        { 
          # yes, this is too much, restitute outer braces
          set text "{$text}"
          # and stop
          break 
        }
        # check for asked nesting
        incr level -1
      }
      return $text
    }

Results:

  set text "{{{this is} a {nested list}}}"
  puts [striplist $text]
  -> {this is} a {nested list}

  set text "{{{this is} a {nested list}}}"
  puts [striplist $text 1]
  -> {{this is} a {nested list}}

  set text "{{{this is} a {nested list}}}"
  puts [striplist $text 2]
  -> {this is} a {nested list}

AEC, 2002-05-28

I use the built-in command join to do the same thing.

 set text "{{{this is} a {nested list}}}"
 {{{this is} a {nested list}}}
 %   set textt [join $text]
 {{this is} a {nested list}}
 %   set textt [join [join $text]]
 {this is} a {nested list}
 %   set textt [join [join [join $text]]]
 this is a nested list

This could easily be encapsulated into a proc to simplify use:

 proc striplist {args} { 
     # Usage:
     #
     # striplist ?-level num? list
     #
     # Level defaults to 0 if omitted.  This means all levels of list nesting
     #   are removed by the proc.  For each level requested, a level of list nesting
     #   is removed.
     #
     # determine level
     set idx [lsearch $args -level]
     if {$idx == 0} {
         set level [lindex $args [incr idx]]
         set args [lreplace $args [expr $idx - 1] $idx]
     } else {
         set level 0
     }
     # while text seems braced and level is not exhausted
     while {1} { 
         # strip outer braces and expose inners
         incr level -1 
         set newargs [join $args]
         if {$newargs == $args} {
             break
         } else {
             set args $newargs
         }
         if {$level == 0} {
             break
         }
     }
     return $args
 }

Example usage:

 % set a {this {is a} test}
 % striplist -level 1 $a
 this {is a} test
 % striplist -level 2 $a
 this is a test