我正在文件系统中使用通配符来遍历文件。为了避免重复计算,我使用已经捕获的文件列表,然后使用lserach进行检查。现在完整文件路径的名称很长,我要访问成千上万个文件。 lsearch查找的速度真的很慢。
在简化版本中,它看起来像这样。
foreach fn [ glob $pattern ] {
if {[lsearch $done $fn] == -1} {
lappend done $fn
# Do somethig with $fn
} else {
#puts "Duplicate fn not processed."
}
}
随着时间的流逝,lsearch必须在越来越长的列表中查找相当长的字符串。有什么可以改善的呢?我当时正在考虑通过使用某种CRC来将字符串缩短,并将其放入完成列表中。但是指纹计算的时间不应该超过搜索时间。
答案 0 :(得分:1)
有两种选择,可以使您仅对是否存在文字字符串感兴趣(由于模式来自SqlCommand cmd = new SqlCommand("dbo.Insertstoredprocedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@ManagerComment", SqlDbType.NVarChar, 255);
cmd.Parameters["@ManagerComment"].Value = " ♦☺♦♣◘•";
,这对我来说很可能):
如果可以确保要搜索的列表按字母顺序排序,则glob
的速度要快得多(数据大小为O(log n),而不是O(n);它进行二进制搜索)。一次性对列表进行排序可能值得。
如果您只在乎该值是否存在,则可以将列表项作为键加载到字典或数组中;然后检查值的存在(lsearch -sorted
或dict exists
)是非常便宜的操作,即使有大量数据也是如此。在幕后,字典和数组是哈希表,因此非常适合此类情况。
如果您要逐步建立列表,以防止重复工作(听起来像您),那么选项2绝对是最好的选择。
答案 1 :(得分:0)
我发现了一个更好的主意,即先将所有内容附加到列表中,然后在末尾进行唯一化。因此只需要遍历该列表。
set all_fn {}
foreach fn $files {
regsub {stuff} $fn {stuff_with_wildcards} pattern
set all_fn [concat $all_fn [ glob $pattern ] ]
}
set all_fn_u [ lsort -unique $all_fn ]
foreach fn $all_fn_u {
#Do something with $fn
}
答案 2 :(得分:0)