#file #sorting #tcl
#файл #сортировка #tcl
Вопрос:
У меня есть список файлов и отдельный список размеров этих файлов, используя «размер файла <имя_файла>».
Мне требуется отсортировать файлы в порядке возрастания на основе размера, а затем отправить их для дальнейшей обработки.
Может кто-нибудь предоставить пошаговый процесс, которому я мог бы следовать?
Это то, что я делал до сих пор
set direc "<Any direcotry to look files at>"
set folderFiles [glob -directory $direc -nocomplain -type f *.xml]
set fileSizes []
puts "Files to be processed are:"
puts "$folderFiles"
puts "Sizes of files in this order are:"
foreach tempFile $folderFiles {
lappend fileSizes [file size $tempFile]
}
puts $fileSizes
set fileDict [dict create [lindex $folderFiles 0] [lindex $fileSizes 0]]
for {set i 1} {$i < [llength $folderFiles]} {incr i} {
dict lappend fileDict [lindex $folderFiles $i] [lindex $fileSizes $i]
}
puts $fileDict
Итак, это дает мне словарь, где ключи -> файлы и значения -> размеры файлов. Мне просто нужно отсортировать этот словарь на основе значений, которые являются размерами файлов.
Комментарии:
1. Считается хорошей практикой попробовать что-то, а затем прийти к SO с проблемами с тем, что вы пробовали. Это звучит как запрос «напишите код для меня», который граничит с грубостью. (Подсказка: прочитайте документацию для
lsort
)2. @Andreas Я новичок в StackOverflow. В любом случае, я приложил усилия. Я отредактировал свой вопрос.
Ответ №1:
Первое, что вам нужно сделать, это получить список имен файлов и их размеров. Вы можете сохранить размеры отдельно.
set filenames [glob -type f *.foo]; # Or whatever
set sizes [lmap f $filenames {file size $f}]
Затем мы сортируем размеры, но возвращаем индексы сортировки, а не отсортированный список.
set indices [lsort -indices -integer $sizes]
Теперь мы используем эти индексы для построения отсортированных имен файлов:
set filenames [lmap idx $indices {lindex $filenames $idx}]
Мы можем объединить некоторые из этих вещей во вспомогательную процедуру:
proc SortFilesBySize {filenames} {
set sizes [lmap f $filenames {file size $f}]
return [lmap idx [lsort -indices -integer $sizes] {lindex $filenames $idx}]
}
set filenames [glob -type f *.foo]; # Or whatever
puts [join [SortFilesBySize $filenames] "n"]
Комментарии:
1. Обратите внимание, что получение размера файлов является сравнительно дорогостоящим, поскольку требует доступа к файловой системе; это означает, что, хотя можно использовать пользовательский компаратор, который использует
file size
каждый раз, это медленный метод, особенно с большим количеством файлов. В отличие от этого, подходы, которые извлекают размер каждого файла только один раз, на практике намного быстрее.
Ответ №2:
Один из способов:
#!/usr/bin/env tclsh
proc zip {list1 list2} {
lmap a $list1 b $list2 { list $a $b }
}
proc heads {pairs} {
lmap pair $pairs { lindex $pair 0 }
}
proc sort_by_size {names sizes} {
heads [lsort -integer -increasing -index 1 [zip $names $sizes]]
}
set names {a.txt b.txt c.txt}
set sizes {3 2 1}
puts [sort_by_size $names $sizes]
Объединяет имена и размеры в список пар имени файла и размера, сортирует по размеру, а затем возвращает только переупорядоченные имена файлов. По сути, это tcl
версия perl
классической идиомы преобразования Шварца.