加快TCL搜索长字符串的长列表的速度

时间:2019-09-26 00:03:11

标签: tcl

我正在文件系统中使用通配符来遍历文件。为了避免重复计算,我使用已经捕获的文件列表,然后使用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来将字符串缩短,并将其放入完成列表中。但是指纹计算的时间不应该超过搜索时间。

3 个答案:

答案 0 :(得分:1)

有两种选择,可以使您仅对是否存在文字字符串感兴趣(由于模式来自SqlCommand cmd = new SqlCommand("dbo.Insertstoredprocedure", connection); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add("@ManagerComment", SqlDbType.NVarChar, 255); cmd.Parameters["@ManagerComment"].Value = " ♦☺♦♣◘•"; ,这对我来说很可能):

  1. 如果可以确保要搜索的列表按字母顺序排序,则glob的速度要快得多(数据大小为O(log n),而不是O(n);它进行二进制搜索)。一次性对列表进行排序可能值得。

  2. 如果您只在乎该值是否存在,则可以将列表项作为键加载到字典或数组中;然后检查值的存在(lsearch -sorteddict 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)

跟进Donal的建议:

  

您可以将列表项作为键加载到字典或数组中

set d [dict create {*}[string cat [join [glob {*}$patterns] " _ "] " _"]]
foreach fn [dict keys $d] {
  puts $fn
}
  • glob一次可以处理多种模式,而无需一次只喂一种。
  • 使用join从glob的结果中创建大小均匀的元素列表(其字符串表示形式)。
  • 使用dict create将Tcl列表的结果字符串rep加载到字典中。
  • 使用dict keys获取(唯一的)键列表。