Как мне эффективно (mem / time) изменить все элементы списка в Tcl? - PullRequest
5 голосов
/ 11 октября 2011

Для работы с каждым элементом списка, возвращая измененный список, различные языки имеют явные конструкции.

В Perl есть карта:

perl -e 'my @a = (1..4); print join(q( ), map { $_ * $_ } @a)'
1 4 9 16

В Python есть списочные выражения:

>>> a = (1,2,3,4)
>>> [el*el for el in a]
[1, 4, 9, 16]

Какой самый эффективный способ сделать это в Tcl?Я могу придумать обычный цикл foreach.

set l {}
foreach i {1 2 3 4} {
    lappend l [expr $i * $i]
}
puts $l
1 4 9 16

Это самый быстрый способ?

Что касается эффективности памяти, это создает второй список, один за другим.Если мне не нужен список постоянно, есть ли более эффективный способ?

И, наконец, есть что-то более короткое?Я не смог найти информацию здесь или в ответе http://wiki.tcl.tk

:

Как ответил Донал Феллоус, что особенно важно для скоростных тестов, все должно быть включено в процесс {} после Tclтогда можно оптимизировать.Для Tcl функция «карта» обсуждается как будущее усовершенствование.С этим подсказкой и дальнейшим поиском я нашел http://wiki.tcl.tk/12848

Ответы [ 2 ]

8 голосов
/ 11 октября 2011

Самый эффективный метод такой:

set idx 0
foreach item $theList {
    lset theList $idx [expr {$item * $item}]
    incr idx
}

Если список короткий (например, несколько сотен элементов), то стоимость выделения нового списка минимальна, поэтому вы можете использовать эту (более простую) версию вместо:

foreach item $theList {
    lappend newList [expr {$item * $item}]
}

Обратите внимание, что команда foreach имеет значение only fast, если помещено в процедуру (или лямбда-выражение или метод), и выражения only fast, если помещено в { фигурные скобки }. Кроме того, не спекулируйте, измерьте : позаботьтесь о том, чтобы с помощью команды time выяснить, насколько быстрым является ваш код.

1 голос
/ 13 октября 2011

Ну, есть что-то более короткое (используя пакет tcllib struct :: list ), но не обязательно быстрее.

package require struct::list
puts [struct::list mapfor x $data { expr {$x * $x} }]
...