简介:(不一定需要回答我的问题,但可能会有所帮助)
我有一个块,里面有多个块(儿子)。 对于每个这样的块(或子块),我正在读取其DEF(设计交换格式)文件并将其所有实例名称分配给一个列表。 因此,我从我读取的所有 DEF 文件中创建了一个包含所有实例名称的列表。 此外,我有一个 primeTime 会话,其中包含块中的所有实例(包括"儿子"块)。
我的问题:
如何在列表中高效搜索部分实例名称?
阐述:
假设我有一个名为DefInstsLst
的列表,其中包含数千个实例名称(如简介中所述,从 DEF 文件中读取)。 例如,此列表包含以下实例名称:
DRO_TAP_31__ap_dro_tap/keep_dro_nr
现在,从 primeTime 读取的顶部块的完整实例名称如下:
ld_top_dft_top/dro_cluster/genblk1_DRO_PACK_0__ap_dro_pack/genblk1_5__DRO_TEL_ap_dro_cell_5nm_7t_TEL/ap_dro_v2_cell/DRO_CELL_DRO_TEL_ap_dro_delay_5nm_7t_TEL/DRO_TAP_31__ap_dro_tap/keep_dro_nd
现在我想根据它的后缀DRO_TAP_31__ap_dro_tap/keep_dro_nd
在我的列表中找到这个实例DefInstsLst
,但由于它是一个巨大的列表,所以我必须有效地搜索它(我正在对 primeTime 会话中的每个实例进行这种搜索)。 我尝试使用lsort
命令对列表进行排序,然后lsearch -sorted
有效地搜索,但是当使用标志-sorted
时,我无法搜索部分模式,而只能搜索完全匹配。 当搜索名称完全匹配的实例时,我用lsearch
描述的方式在运行时方面非常有效。
由于您正在寻找后缀,因此您没有任何选择比不涉及大量准备工作的lsearch -glob *$pattern
更有效。排序无济于事,因为这是从字符串的开头开始的。该 glob(前面有一个*
)的效率与您进行单个字符串检查的效率一样高;它是球形匹配机械中优化的案例之一。
你可能做的准备工作?准备另一个列表,这些值全部颠倒并对其进行排序。然后,您可以在开头查找反向模式,这是可以通过二叉搜索有效地完成的(这正是lsearch -sorted
所做的)。这可能是很多开销!或者,您可以拆分字符串以提取某种排序规则键;它的适用性取决于您正在寻找的内容。这两者都有很多开销;每个列表条目都会获得额外的数据,可能与列表条目本身一样大。(如果有很多,请考虑使用数据库;SQLite非常出色,并且与Tcl集成得很好。
我同意Donal的观点,一些准备工作可能是你最好的选择。 以不同的方式重新排列所有数据,使其在此类搜索中更有效。
例如,您可以遍历所有实例名称,并按后缀将它们排列到字典中:
set suffix_dict [dict create]
foreach instance_name $instance_names {
# Assume the suffix are the last two parts full hierarchical instance name
set suffix [join [lrange [split $instance_name "/"] end-1 end] "/"]
dict lappend suffix_dict $suffix $instance_name
}
set suffix_lookup "DRO_TAP_31__ap_dro_tap/keep_dro_nr"
set matching_instances [dict get $suffix_dict $suffix_lookup]
准备字典是一次性成本,但之后是快速的字典查找。
另一个想法是将lsearch
命令放入进程。 每次调用 proc 时,都会缓存 args 的结果。
set cache [dict create]
proc lookup_instance {pattern} {
# Check cache first
if {[dict exists $::cache $pattern]} {
return [dict get $::cache $pattern]
}
set matches [lsearch -sorted -all -inline $::instance_names]
# Save to cache
dict set ::cache $pattern $matches
return $matches
}
如果您经常查找相同的模式,这将节省时间。