'Rearrange array based on index/value
I have a TCL array , say arr. It has the following contents :
set arr(apple) "red"
set arr(grape) "green"
set arr(one) 1
set arr(2) "two"
set arr(0) "ZERO"
set arr(banana) "yellow"
set arr(three) 3
My aim is to push the element with index 0 to the last while maintaining the same order. I tried this solution
set arrList [array get arr]
foreach {key val} $arrList {
if {$key==0} then {
set a [lsearch $arrList $key]
set arrList [lreplace $arrList $a [incr a]]
lappend arrList $key $val
}
}
array set arr $arrList
My idea was to append the element and it's value (0 and "ZERO") and then convert it back again to an array. But then I realized that TCL array are implemented as Hash Table , so order can't be preserved.
So is there any way to solve this problem ? And if I have made any mistake anywhere , please do the required corrections. PS : I don't know if this is repeated.
Thanks
Solution 1:[1]
There's a key problem here: arrays have no order of keys at all. It's random. (Well, it's deterministic based on the exact history of the hash table behind the array; the algorithm is sufficiently complex that nobody remembers it. It's certainly allowed to change when the storage is resized.)
To keep any kind of order of keys, you need to have a list of them. To move the element 0 to the end there:
set keylist {apple grape one 2 0 banana three}
set idx [lsearch -exact $keylist "0"]
if {$idx >= 0} {
# This doesn't assume that you already know the value at $idx
# You actually do here, but we show the general case
set keylist [list {*}[lreplace $keylist $idx $idx] [lindex $keylist $idx]]
}
Once you've got the order, printing out the array is just:
foreach key $keylist {
puts "set array($key) \"$array($key)\""
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Donal Fellows |
