如果在Perl中键相同,则将值追加到哈希
问题是读取每一行都有值的文件。文件的内容看起来像如果在Perl中键相同,则将值追加到哈希,perl,hash,Perl,Hash,问题是读取每一行都有值的文件。文件的内容看起来像 3ssdwyeim3,3ssdwyeim92017-03-16,09:10:35.372,0.476,EndInbound 第三天,第三天,2017-03-16,09:10:35.369,0.421,内出 3ssdwyfxc0,3ssdwyfxfi,2017-03-16,09:10:35.456,0.509 3ssdwyfxc0,3ssdwyhg0v,2017-03-16,09:10:35.453,0.436,内出 第一个逗号前的字符串是键,最
3ssdwyeim3,3ssdwyeim92017-03-16,09:10:35.372,0.476,EndInbound
第三天,第三天,2017-03-16,09:10:35.369,0.421,内出
3ssdwyfxc0,3ssdwyfxfi,2017-03-16,09:10:35.456,0.509
3ssdwyfxc0,3ssdwyhg0v,2017-03-16,09:10:35.453,0.436,内出
第一个逗号前的字符串是键,最后一个和最后第二个逗号之间的字符串是值
i、 e.对于第一行,3ssdwyeim3成为键,0.476值
现在,当我们在每一行上循环时,如果键存在,我们必须连接由逗号分隔的值
因此,对于下一个新行,由于键已存在,键仍保留3ssdwyeim3
,但值更新为0.476,0.421。
最后,我们必须打印文件中的键和值
我已经写了一个代码来实现同样的功能,如下所示
sub-findbreakdown{
我的($out)=@;
我的%timeLogger;
打开读取,“out.txt”或“die”无法打开.txt进行读取:$!”;
OpenOutBD,“>$out\\u breakdown.csv”或die“无法打开$out\\u breakdown.csv进行写入:$!”;
而(){
如果(/(.*)、.*、.*、(.*)、.*/){
$btxnId=$1;
$time=$2;
if(!$timeLogger{$btxnId}){
$timeLogger{$btxnId}=$time;
}
否则{
$previousValue=$timeLogger{$btxnId};
$newValue=join“,”,$previousValue,$time;
$timeLogger{$btxnId}=$newValue;
}
}
foreach(排序键%timeLogger){
打印输出BD“$\$timeLogger{$\}\n”;
}
}
闭关自守;
仔细阅读;
}
然而,有些地方出了问题,它的印刷方式是这样的
3ssdwyeim3,0.476
3ssdwyeim3,0.476,0.421
3ssdwyeim3,0.476,0.421
3ssdwyfxc0,0.509
3ssdwyeim3,0.476,0.421
3ssdwyfxc0,0.509,0.436
3ssdwyeim3,0.476,0.421
3ssdwyfxc0,0.509,0.436
鉴于预期为:
3ssdwyeim3,0.476,0.421
3ssdwyfxc0,0.509,0.436
您的程序运行正常,但在处理每一行后,您正在打印整个哈希的当前状态。
因此,在散列键具有完整的值集之前打印它们,并且有许多重复的行
如果将打印到程序末尾的foreach
循环移动(或者简单地使用调试器检查变量),您将发现哈希的最终状态正是您所期望的
编辑:我之前认为问题出在下面,但这是因为我误读了您问题中的样本数据 此正则表达式不理想:
if (/(.*),.*,.*,.*,(.*),.*/) {
*
是贪婪的,将尽可能多地匹配(包括一些带有逗号的内容)。因此,如果任何一行包含六个以上逗号分隔的项,那么第一个匹配组中将包含多个项。在实际数据中,这可能不是问题,但这不是编写代码的理想方式。这个表达式的含混不清
最好这样写:
if (/^([^,]*),[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$/) {
这将只匹配正好有六个项目的行
或考虑在输入行上使用拆分,这将是一个更干净的解决方案。
<强>您的程序运行正常,但在处理每一行之后,您正在打印整个哈希的当前状态。>/P> 因此,在散列键具有完整的值集之前打印它们,并且有许多重复的行
如果将打印到程序末尾的foreach
循环移动(或者简单地使用调试器检查变量),您将发现哈希的最终状态正是您所期望的
编辑:我之前认为问题出在下面,但这是因为我误读了您问题中的样本数据 此正则表达式不理想:
if (/(.*),.*,.*,.*,(.*),.*/) {
*
是贪婪的,将尽可能多地匹配(包括一些带有逗号的内容)。因此,如果任何一行包含六个以上逗号分隔的项,那么第一个匹配组中将包含多个项。在实际数据中,这可能不是问题,但这不是编写代码的理想方式。这个表达式的含混不清
最好这样写:
if (/^([^,]*),[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$/) {
这将只匹配正好有六个项目的行
或考虑在输入行上使用拆分,这将是一个更干净的解决方案。
< P>这比你所做的要简单得多。您只需将每一行拆分为字段,然后使用push
将值添加到与键对应的列表中
我相信您可以将其修改为从外部文件读取,而不是从数据
文件句柄读取
使用严格;
使用“全部”警告;
我的%数据;
而(){
我的@fields=split/,/;
推送{$data{$fields[0]},$fields[-2];
}
对于我的$key(对key%数据进行排序){
打印联接(“,”,$key,@{$data{$key}),“\n”;
}
__资料__
3ssdwyeim3,3ssdwyeim92017-03-16,09:10:35.372,0.476,EndInbound
第三天,第三天,2017-03-16,09:10:35.369,0.421,内出
3ssdwyfxc0,3ssdwyfxfi,2017-03-16,09:10:35.456,0.509
3ssdwyfxc0,3ssdwyhg0v,2017-03-16,09:10:35.453,0.436,内出
输出
3ssdwyeim3,0.476,0.421
3ssdwyfxc0,0.509,0.436
这比您所做的要简单得多。您只需将每一行拆分为字段,然后使用push
将值添加到与键对应的列表中
我相信您可以将其修改为从外部文件读取,而不是从数据
文件句柄读取
使用严格;
使用“全部”警告;
我的%数据;
而(){
我的@fields=split/,/;
推送{$data{$fields[0]},$fields[-2];
}
对于我的$key(对key%数据进行排序){
打印联接(“,”,$key,@{$data{$key}),