Dictionary Perl';Tcl中dict的Hash等价实现
我有一个非常大的文件,其中包含如下数据:Dictionary Perl';Tcl中dict的Hash等价实现,dictionary,hash,nested,tcl,Dictionary,Hash,Nested,Tcl,我有一个非常大的文件,其中包含如下数据: *1 RES L1 N1 0.32 *22 RES L2 N2 0.64 *100 CAP A1 B1 0.3 *200 CAP A2 B1 0.11 *11 IND K1 K2 0.002 *44 IND X1 Y1 0.00134 ... and so on 对于这些文件(假设上面的数据在一个名为“example.txt”的文件中),我可以轻松地在Perl中创建散列,并将这些嵌套的散列传递给Perl程序的其他部分: #!/usr/bin/pe
*1 RES L1 N1 0.32
*22 RES L2 N2 0.64
*100 CAP A1 B1 0.3
*200 CAP A2 B1 0.11
*11 IND K1 K2 0.002
*44 IND X1 Y1 0.00134
... and so on
对于这些文件(假设上面的数据在一个名为“example.txt”的文件中),我可以轻松地在Perl中创建散列,并将这些嵌套的散列传递给Perl程序的其他部分:
#!/usr/bin/perl
use strict;
use warnings;
open(FILE,"<", "example.txt") or die "Cannot open file:$!";
if (-f "example.txt") {
while(<FILE>) {
chomp;
if(/^\s*(\S+)\s+(RES|CAP|IND)\s+(\S+)\s+(\S+)\s+(\S+)\s*$/) {
$hoh{$1}{$2}{$3}{$4} = $5;
}
}
close FILE;
}
但这似乎不起作用。我对它进行了如下测试:
foreach id [dict keys $dod] {
if [dict exists $dod "RES"] {
puts "RES KEY EXISTS"
} else {
puts "RES KEY NOT FOUND"
}
}
谢谢。不完全一样,但有些相似:
set data "*1 RES L1 N1 0.32
*22 RES L2 N2 0.64
*100 CAP A1 B1 0.3
*200 CAP A2 B1 0.11
*11 IND K1 K2 0.002
*44 IND X1 Y1 0.00134
"
set pattern {\s*(\S+)\s+(RES|CAP|IND)\s+(\S+)\s+(\S+)\s+(\S+)?\s*$}
set result [regexp -all -line -inline -- $pattern $data]
if {[llength $result] == 0} {
puts "Not found"
exit 1
}
array set my_data {}
foreach {all ind_0 ind_1 ind_2 ind_3 ind_4} $result {
set my_data($ind_0)($ind_1)($ind_2)($ind_3) $ind_4
}
puts [parray my_data]
样本输出:
my_data(*1)(RES)(L1)(N1) = 0.32
my_data(*100)(CAP)(A1)(B1) = 0.3
my_data(*11)(IND)(K1)(K2) = 0.002
my_data(*200)(CAP)(A2)(B1) = 0.11
my_data(*22)(RES)(L2)(N2) = 0.64
my_data(*44)(IND)(X1)(Y1) = 0.00134
您眼前的问题是正则表达式开头的斜杠 回答这个问题:多键词典是“散列”。每个键都会添加一个新级别的字典
dict set foo aa bb cc 1
设置字典中的成员{cc 1}
,该成员是foo
中的成员{bb…}
的值
如果您不想使用多级词典,但仍然需要使用多个键值,则需要执行以下操作:
dict set foo [list aa bb cc] 1
另外,我不知道在您的示例中简化了多少,但是添加项目的代码可以更好地表述为:
if {[lindex $line 1] in {RES CAP IND}} {
dict set dod {*}$line
}
但是,如果要通过例如“RES”来检查是否存在,则需要将其设置为顶级键,而在示例中没有设置(第一列中的项目将成为顶级键)。如上所述初始化,dod
的值为
*1 {RES {L1 {N1 0.32}}} *22 {RES {L2 {N2 0.64}}} *100 {CAP {A1 {B1 0.3}}} *200 {CAP {A2 {B1 0.11}}} *11 {IND {K1 {K2 0.002}}} *44 {IND {X1 {Y1 0.00134}}}
所以你确实得到了一本字典,但dict exists$dod RES仍然必然是假的。利用
if {[lindex $line 1] in {RES CAP IND}} {
dict set dod {*}[lrange $line 1 end]
}
(即,第一个作为键之后的行中的所有项目,最后一个成为值除外)您将获得字典
RES {L1 {N1 0.32} L2 {N2 0.64}} CAP {A1 {B1 0.3} A2 {B1 0.11}} IND {K1 {K2 0.002} X1 {Y1 0.00134}}
你可以测试“RES”的存在
回到圣经的圣经
*1 {RES {L1 {N1 0.32}}} *22 {RES {L2 {N2 0.64}}} *100 {CAP {A1 {B1 0.3}}} *200 {CAP {A2 {B1 0.11}}} *11 {IND {K1 {K2 0.002}}} *44 {IND {X1 {Y1 0.00134}}}
您可以通过检查每个子字典来检查“RES”,直到找到具有该键的子字典:
set found 0
dict for {key subdict} $dod {
if {[dict exists $subdict RES]} {
set found 1
break
}
}
文件:
请注意,这不是“散列”,而是一个具有复杂键的单级关联数组。请注意,Tcl不支持多维键。上面第一项的关键是
*1)(RES)(L1)(N1
。它仍然有效,但使用的格式意味着一些不存在的功能。我将使用与不同的分隔符。)(
。逗号、破折号、句点都很好。如果需要对键进行排序,则应仔细选择键的格式。Peter,很抱歉,我在原始问题中复制/粘贴时出错。对于Tcl部分,正则表达式应该是:`If[regexp{^\s*(\s+)\s+(RES|CAP|IND)\s+(\s+)(\s+)(\s+)\s+)\s*}$line…`如果您在查询数据时做了一些非常复杂的事情,那么将其转储到内存中的SQLite数据库是很容易的。嗨,多纳尔,有没有关于如何将Tcl与内存中的SQLite一起使用的文档?我想试试看我是否可以继续使用该解决方案。谢谢。@user3512999:我不知道最好的文档是什么,但h你看过这里吗
set found 0
dict for {key subdict} $dod {
if {[dict exists $subdict RES]} {
set found 1
break
}
}