我创建了一个子程序,用于在下面分隔的制表符中创建HoA。
header_map.txt:
def test_email(data)
notif_type = data['notif_type']
emails_list = ['132xxy@yahoo.com', '133xxy@yahoo.com']
subject = case notif_type
when 'test_case_1'
"test1"
when 'test_case_2'
"test2"
when 'test_case_3'
"test3"
mail(:to => emails_list, :subject => subject) do |format|
format.html { render :layout => 'layouts/newdesign' }
end
end
sub然后将数组从给定键的值反弹(如下所示)。 其中值与数组匹配,索引为 返回匹配的数组元素。 我想要做的不是搜索预定义的常量数组, 我想搜索从文件中读取的数组,或者在本例中搜索数据。 下面是常量数组的工作代码。
account_number_header account
account_number_header Account #
account_number_header Account No.
account_number_header Account number
account_number_header Account_Id
first_Name_header name1
first_Name_header first name
first_Name_header account name1
first_Name_header first_name
first_Name_header f name
last_Name_header name2
last_Name_header last name
last_Name_header account name2
last_Name_header last_name
last_Name_header l name
address_header address1
address_header address
address_header addresses
address_header place of residency
address_header location
结果
my @fields = ('Account No.','name1','name2','location'); #array being searched
my $hm = "header_map.txt"; #declare variable to file
my $fh = (readfile($hm)); #declare variable to sub routine call
my $address_header = 'address_header'; #my given key
my $address = hashofarray($fh,$address_header); #looking for($fh,key) in sub
my $account_number_header = 'account_number_header'; #my given key
my $account_number = hashofarray($fh,$account_number_header); #looking for($fh,key) in sub
print $address,",",$account_number,"\n"; #prints desired array indexes of given keys
sub hashofarray {
my $fh = shift;
my $key = shift;
my %hash;
while (<$fh>) { # creating HoA
chomp;
my ( $key, $value ) = split /\t/;
push (@{ $header_map{$key} }, $value);
}
foreach my $key1 (@{$header_map{$key}}) {
if (my @index = grep { $fields[$_] eq $key1 } 0..$#fields) {
return $index[0];
}
}
}
sub readfile {
my $file = shift;
open my $f, '<', $file or die $!;
return $f;
}
这很好,我想要的,但是我想从DATA文件中读取数组@fields。 这是我在阅读DATA时的尝试。
尝试失败
location,Account No.
我的结果
my $hm = "O:/josh/trade_data/mock_header_map.txt"; # declare variable to file
my $fh = (readfile($hm)); # declare variable to sub routine call
while (<DATA>) { # calling the subroutine after reading DATA
my @fields = split /\t/;
my $address_header = 'address_header'; # my given key
my $address = hashofarray($fh, $address_header); # looking for($fh, key) in sub
my $account_number_header = 'account_number_header'; # my given key
# looking for($fh, key) in sub
my $account_number = hashofarray($fh, $account_number_header);
# prints desired array indexes of given keys
print $address, ",", $account_number, "\n";
}
sub hashofarray {
my $fh = shift;
my $key = shift;
my %hash;
while (<$fh>) { #creating HoA
chomp;
my ( $key, $value ) = split /\t/;
push (@{ $header_map{$key} }, $value);
}
foreach my $key1 (@{$header_map{$key}}) {
if(my @index = grep { $fields[$_] eq $key1 } 0..$#fields) {
return $index[0];
} else {
print "not found";
}
}
}
sub readfile {
my $file = shift;
open my $f, '<', $file or die $!;
return $f;
}
__DATA__
Account No name1 name2 location
1 josh smith 411 s chirris ave. sometown st 12345
1 josh smith 411 s chirris ave. sometown st 12345
1 josh smith 411 s chirris ave. sometown st 12345
1 josh smith 411 s chirris ave. sometown st 12345
期望的结果
,
,
,
,
,
最后,我想打印所需的列,如果我可以将DATA读入数组,我将能够做到这一点,而不是因为sub不能识别@fields而得到空字符串。 我知道我需要对数组引用做一些事情,但我对这些有点偏僻......有什么建议吗?我希望这很清楚。
答案 0 :(得分:1)
hashofarray
函数尝试读取文件句柄。然后迭代到文件的末尾。然后......再次调用它,当没有更多文件可供阅读时。
但这不是唯一的问题 - 有几个问题。如果你从数组的散列中重写密钥......为什么不使用散列哈希呢? 你做
同样 - @fields
不是全局范围的,因此当您尝试在hashofarray
中重复使用时......它总是空的。
我可以建议退一步吗?用您的实际问题规范更新您的问题(或询问新问题)?包括输入数据和预期输出。
我认为您已经经历了几个修复此代码的周期,并且它变得混乱,所以我认为是时候退缩一点并重新开始。我想你会发现那里有更清洁,更优雅的解决方案。
那就是说 - 如果您只是想提取标题&#39;来自现有数据块的行:
my @fields = split /\t/,<DATA>; #read first line, split into array.
while ( <DATA> ) { #etc.
您可以 - 例如 - 翻译您的数据&#39;像这样的数据结构:
use strict;
use warnings;
use Data::Dumper;
my @all_records;
my $header_line = <DATA>;
chomp($header_line);
my @headers = split /\t/, $header_line;
while (<DATA>) {
chomp;
my @columns = split /\t/;
my %record;
@record{@headers} = @columns;
print Dumper \%record;
push( @all_records, \%record );
}
print Dumper \@all_records;
foreach my $record ( @all_records ) {
print join ",", $record -> {'Account No'}, $record -> {'location'},"\n";
}
__DATA__
Account No name1 name2 location
1 josh smith 411 s chirris ave. sometown st 12345
1 josh smith 411 s chirris ave. sometown st 12345
1 josh smith 411 s chirris ave. sometown st 12345
1 josh smith 411 s chirris ave. sometown st 12345
我建议 - 你可以使用&#39;帐号&#39;作为一个独特的键,可能所以你实际上并不需要使用数组。你在这个的情况下做了,所以我已经在我的代码中完成了这个。
这将打印:
1,411 s chirris ave. sometown st 12345,
1,411 s chirris ave. sometown st 12345,
1,411 s chirris ave. sometown st 12345,
1,411 s chirris ave. sometown st 12345,
答案 1 :(得分:0)
你在我的内部循环声明@fields
。
while (<DATA>) { # calling the subroutine after reading DATA
my @fields = split /\t/;
因此该变量的范围仅限于while循环。而不是这样做尝试在循环时声明数组@fields
。
另请将这些放在代码顶部。
use strict;
use warnings;
如果这些行位于顶部,您将发现此错误。
此外,您还需要改进阅读文件的方式。当您第一次阅读$fh
时,搜索指针将最后到达,之后您的代码将永远不会从文件中读取任何内容。它将适用于第一次迭代中创建的哈希。因此,如果您只需一次阅读文件,请将该阅读部分从其他内容中取出,如果您想要一次又一次阅读,请关闭$fh
并重新打开它。
if(my @index = grep { $fields[$_] eq $key1 } 0..$#fields) {
不会提供来自@fields
的实际字词,而是会提供来自@fields
的匹配字词的索引,因此在打印时应该使用
print $fields[$address],",", $fields[$account_number], "\n";
我希望在完成这些更改之后,您将能够为您的问题撰写正确的解决方案。