Reputation: 1141
I have two lists that contain some data (numeric data or/and strings)?
How do I join these two lists, assuming that the lists do not contain sublists?
Which choice is preferred and why?
set first [concat $first $second]
lappend first $second
append first " $second"
Upvotes: 12
Views: 48467
Reputation: 111
As of 2024 - my tests indicate
lappend first {*}$second
is many times faster (especially for larger lists) than
set first [list {*}$first {*}$second]
(in tcl 8.6, 8.7 and 9.0) It's been a long time since DKF answered - so perhaps a fair bit has changed in the list implementation in that time.
Upvotes: 1
Reputation: 468
To add to the other answers, I ran a rough benchmark comparing the different versions (tclsh 8.6.13).
#! /usr/bin/env tclsh
set a {1}
for {set i 0} {$i < 25} {incr i} {
switch $argv {
list {
set a [list {*}$a {*}$a]
}
concat {
set a [concat $a $a]
}
lappend {
lappend a {*}$a
}
append {
append a " $a"
}
}
}
Results:
./test.tcl lappend 0.28s user 0.51s system 99% cpu 0.795 total
./test.tcl list 0.22s user 0.29s system 99% cpu 0.511 total
./test.tcl append 0.04s user 0.08s system 99% cpu 0.115 total
./test.tcl concat 0.04s user 0.08s system 99% cpu 0.112 total
Note that the semantics aren't quite the same between the different versions. For example, list
will re-quote list elements.
Upvotes: 0
Reputation: 145
Maybe a bit old, but wanted to clarify;
As already stated, the standard way to merge 2 lists is via concat
pre-v8.6. However please note that concat
gets very inefficient when dealing with long lists, since it analyzes the lists as part of the merge. eg when merging lists, the larger they get the slower they merge.
Both appends do not merge "lists", they just add to an existing list (lappend
) or variable (append
). Both appends have no impact to speed, since they do not analyze anything when appending.
If merging single entry list elements, one could merge them via set first [join [lappend first $second]]
but only if dealing with simple/single elements within each list (ie no spaces per element).
Upvotes: 1
Reputation: 137567
It is fine to use concat
and that is even highly efficient in some cases (it is the recommended technique in 8.4 and before, and not too bad in later versions). However, your second option with lappend
will not work at all, and the version with append
will work, but will also be horribly inefficient.
Other versions that will work:
# Strongly recommended from 8.6.1 on
set first [list {*}$first {*}$second]
lappend first {*}$second
The reason why the first of those is recommended from 8.6.1 onwards is that the compiler is able to optimise it to a direct "list-concatenate" operation.
Upvotes: 25
Reputation: 40698
% set first {a b c}
a b c
% set second {1 2 3}
1 2 3
% set first [concat $first $second]; # #1 is correct
a b c 1 2 3
% set first {a b c}
a b c
% lappend first $second; # #2 is wrong: appends the whole `second` list to `first
a b c {1 2 3}
I looked up the documentation, also experiment with some lists and found out that:
concat
is correctlappend
does not work because it treats $second
as one element, not a listappend
works, but you are treating your lists as string. I don't know what the implications are, but it does not communicate the intention that first
and second
are lists.Upvotes: 4