コマンドを使用しtime
てベンチマークも行います。これが私のコードです.2つのメソッドを追加しました.1つは使用array
し、もう1つはstruct::set
重複を排除するために使用します.
#!/usr/bin/env tclsh
#http://stackoverflow.com/questions/18337534/what-way-is-faster-to-populate-a-list-with-unique-values-in-tcl
package require Tclx
package require struct::set
proc removeDupMethod {selectionList} {
set finalList [list ]
foreach selection $selectionList {
regexp {(\d+):(\d+)} $selection -> start end
for {set i $start} {$i <= $end} {incr i} {
lappend finalList $i
}
}
set finalList [lrmdups $finalList]
return $finalList
}
proc searchBeforInsertMethod {selectionList} {
set finalList [list ]
foreach selection $selectionList {
regexp {(\d+):(\d+)} $selection -> start end
for {set i $start} {$i <= $end} {incr i} {
if {[lsearch $finalList $i] == -1} {
lappend finalList $i
}
}
}
}
proc useArrayMethod {selectionList} {
array set tally {}
foreach selection $selectionList {
regexp {(\d+):(\d+)} $selection -> start end
for {set i $start} {$i <= $end} {incr i} {
incr tally($i)
}
}
set finalList [array names tally]
return $finalList
}
proc useStructSetMethod {selectionList} {
set finalList {}
foreach selection $selectionList {
regexp {(\d+):(\d+)} $selection -> start end
for {set i $start} {$i <= $end} {incr i} {
struct::set include finalList $i
}
}
return $finalList
}
# Performs the benchmark on a method
proc bench {methodName} {
set selectionList {1:10 5:20 10:30 4:30}
set timeInfo [time {$methodName $selectionList} 1000]
puts "$methodName - $timeInfo"
}
# main
bench removeDupMethod
bench searchBeforInsertMethod
bench useArrayMethod
bench useStructSetMethod
結果:
removeDupMethod - 281.961364 microseconds per iteration
searchBeforInsertMethod - 93.984991 microseconds per iteration
useArrayMethod - 122.354889 microseconds per iteration
useStructSetMethod - 576.293311 microseconds per iteration
討論
- 2 番目の方法
searchBeforInsertMethod
が最速です。
useArrayMethod
一意性を確保するために配列を使用する が 2 番目になります。これは、TCL の組み込みリスト コマンドが非常に最適化されていることを意味します。
- 驚いたことに、
useStructSetMethod
が最も遅いです。ライブラリ コマンドを最適化する必要があると思っていましたが、間違っていました。
アップデート
私はSiybのヒントを取り、置き換えました:
regexp {(\d+):(\d+)} $selection -> start end
と:
set range [split $selection :]
set start [lindex $selection 0]
set end [lindex $selection 1]
そして、速度が劇的に向上することを確認してください。
removeDupMethod - 9.337442 microseconds per iteration
searchBeforInsertMethod - 5.528975999999999 microseconds per iteration
useArrayMethod - 6.8120519999999996 microseconds per iteration
useStructSetMethod - 5.774831 microseconds per iteration
useNative - 6.105141 microseconds per iteration
ノート
- 最速はそのまま
searchBeforInsertMethod
で、スピードアップは17倍近く。
useStructSetMethod
現在2位に浮上
更新 2
potrzebie の要求に従って、先頭に 5000:6000 を追加しましたが、数値はあまり変わりません。
removeDupMethod - 10.826106 microseconds per iteration
searchBeforInsertMethod - 6.296769 microseconds per iteration
useArrayMethod - 7.752042 microseconds per iteration
useStructSetMethod - 6.910305999999999 microseconds per iteration
useNative - 7.274724 microseconds per iteration