2

I have a list named "a" and need to perform some basic list operations and commands to get the desired result in another list "b"

This list "a" can contain more elements in any order I have shown one example below

(%) set a {{123.4:xyz {p_q[5]}} {123.4:abc {r_s[6]}} mno}

 {{123.4:xyz {p_q[5]}} {123.4:abc {r_s[6]} mno}

Currently, I tried this and got

(%) set b ""
(%)    
(%) foreach l $a {
       lappend b [regsub -all [lindex $l 0] $l ""]
    }
(%) puts $b

 {{p_q[5]}} {{r_s[6]}} {}

Instead I want "b" to have output as follows

p_q[5] r_s[6] mno

Tcl version: 8.4.6

Jerry
  • 70,495
  • 13
  • 100
  • 144
user2643899
  • 165
  • 8
  • What do you want to archive? Mixing lists and strings is never a good idea. You use $l as list (`lindex $l 0`) and as string `regsub ... $l` – Johannes Kuhn Oct 02 '13 at 22:19
  • @Johannes Kuhn: I want to achieve output for list b as written in my last line of the question, that is expected. Next time I will try not mix lists and strings – user2643899 Oct 02 '13 at 22:36
  • @user2643899 if any answer helps and satisfy the question. There is an option to accept the answer. – Vishwadeep Singh Oct 03 '13 at 08:21
  • 3
    You are aware that 8.4.6 is _vastly_ out of date? There are later patches to the 8.4 series; it's up to 8.4.20 now (and you'll need commercial support to go later). That's totally backward compatible, except with many bugs fixed. Or you could switch to 8.5 (now 8.5.15) or 8.6 (now 8.6.1). – Donal Fellows Oct 03 '13 at 08:30

2 Answers2

1

Here is one possible solution, if I understand your problem correctly:

set a {{123.4:xyz {p_q[5]}} {123.4:abc {r_s[6]}} mno}
puts $a

set b [list]
foreach item $a {
    lappend b [lindex $item end]
}
puts ">$b<"
set b [concat {*}$b]
puts ">$b<"

Output:

{123.4:xyz {p_q[5]}} {123.4:abc {r_s[6]}} mno
>{p_q[5]} {r_s[6]} mno<
>p_q[5] r_s[6] mno<

Discussion

  1. The loop goes through each item in list a
  2. For each item, pick out the last sub-item and append it to b
  3. After the list exits, b is almost what you want (see the second line in the output)
  4. A call to concat will fix that to your liking.

Update

Donal Fellows pointed out that instead of using [concat {*}$b], I can use [join $b]. This approach has a couple of advantages which I like:

  • It works on older 8.4 systems, which does not support the {*} construct
  • It is simpler to understand

However, the concat approach offers an advantage: speed. Take a look at the following interactive session:

(Downloads2) 61 % set b {{p_q[5]} {r_s[6]} mno}
{p_q[5]} {r_s[6]} mno
(Downloads2) 62 % time {concat {*}$b} 10000
0.43452700000000005 microseconds per iteration
(Downloads2) 63 % time {join $b} 10000
0.603005 microseconds per iteration

The concat speed is about 30% faster than join in this case.

Hai Vu
  • 37,849
  • 11
  • 66
  • 93
  • Which version of tcl are you using, because I tried the exact same code that you have and I am getting the following error – user2643899 Oct 03 '13 at 04:52
  • {123.4:xyz {p_q[5]}} {123.4:abc {r_s[6]}} mno >{p_q[5]} {r_s[6]} mno< extra characters after close-brace while executing "set b [concat {}$b] puts ">$b<" " (file "t.tcl" line 9) – user2643899 Oct 03 '13 at 04:53
  • 1
    You might prefer to use `[join $b]` instead of `[concat {*}$b]` to remove the braces. That works with 8.4 too. – Donal Fellows Oct 03 '13 at 08:27
  • @Donal, I did not know think about `join`. Thank you for pointing it out. At work, we still have some systems with 8.4, so this is a great tip. For 8.5 and later, I prefer `concat` because it is faster. See my update. – Hai Vu Oct 03 '13 at 16:38
1

So Here is again one liner for you:

% set a {{123.4:xyz {p_q[5]}} {123.4:abc {r_s[6]}} mno}
  {123.4:xyz {p_q[5]}} {123.4:abc {r_s[6]}} mno
% set b [lsearch -all -regexp -not -inline [regsub -all "\{|\}" $a ""] ":"]
{p_q[5]} {r_s[6]} mno

If further, you want to remove {}, then

%set b [regsub -all "\{|\}" $b ""]
Vishwadeep Singh
  • 1,043
  • 1
  • 13
  • 38