我正在编写一段代码,从输入文件中提取一些数字,该文件包含两个条件的信息。因此,代码为每一行提取两个数字,并将它们相互比较。下面的代码片段运行正常,但我无法理解以下哪种方法是“正确的”,以及原因:
输入:
gi|63100484|gb|BC094950.1|_Xenopus_tropicalis_cDNA_clone_IMAGE:7022272 C1:XLOC_017431_0.110169:4.99086,_Change:5.5015,_p:0.00265,_q:0.847141 [95.08] C2:XLOC_020690_0.050681:9.12527,_Change:7.49228,_p:0.0196,_q:0.967194 [95.08]
gi|6572468|emb|AJ251750.1|_Xenopus_laevis_mRNA_for_frizzled_4_protein_(fz4_gene) C1:XLOC_027664_1.61212:4.37413,_Change:1.44003,_p:0.00515,_q:0.999592 [99.40] C2:XLOC_032999_2.94775:14.2322,_Change:2.27147,_p:5e-05,_q:0.0438548 [99.40]
gi|68533737|gb|BC098974.1|_Xenopus_laevis_RDC1_like_protein,_mRNA_(cDNA_clone_MGC:114801_IMAGE:4632706),_complete_cds C1:XLOC_036220_0.565861:6.52476,_Change:3.52741,_p:0.00015,_q:0.21728 [99.95] C2:XLOC_043165_0.157752:2.52129,_Change:3.99843,_p:0.02115,_q:0.99976 [99.95]
gi|70672087|gb|DQ096846.1|_Xenopus_laevis_degr03_mRNA,_complete_sequence C1:XLOC_031048_0.998437:4.20942,_Change:2.07588,_p:0.01365,_q:0.999592 [99.87] C2:XLOC_037051_1.1335:4.36819,_Change:1.94624,_p:0.01905,_q:0.9452 [99.87]
gi|70672102|gb|DQ096861.1|_Xenopus_laevis_rexp44_mRNA,_complete_sequence C1:XLOC_049520_12.3353:6.30193,_Change:-0.968926,_p:0.04935,_q:0.999592 [92.90] C2:XLOC_058958_13.0419:5.10275,_Change:-1.35381,_p:0.0373,_q:0.99976 [92.90]
gi|7110523|gb|AF231711.1|_Xenopus_laevis_7-transmembrane_receptor_frizzled-1_mRNA,_complete_cds C1:XLOC_038309_0.784476:2.37536,_Change:1.59835,_p:0.0079,_q:0.999592 [99.94] C2:XLOC_045678_0.692883:3.52599,_Change:2.34735,_p:0.00125,_q:0.341583 [99.94]
#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp;
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
my @intersect = read_file('text.txt');
my (@q1, @q2, @change_q, @q_values, @q_value1, @q_value2);
foreach (@intersect) {
chomp;
@q_value1 = ($_ =~ /C1:.*?q:(\d+\.\d+)/);
@q_value2 = ($_ =~ /C2:.*?q:(\d+\.\d+)/);
push @q_values, "C1:@q_value1\tC2:@q_value2";
if (abs $q_value1[@_] < abs $q_value2[@_]) {
push @change_q, $q_value1[@_];
}
elsif (abs $q_value2[@_] < abs $q_value1[@_]) {
push @change_q, $q_value2[@_];
}
}
print Dumper (\@q_values);
print Dumper (\@change_q);
输出:
$VAR1 = [
'C1:0.847141 C2:0.967194',
'C1:0.999592 C2:0.0438548',
'C1:0.21728 C2:0.99976',
'C1:0.999592 C2:0.9452',
'C1:0.999592 C2:0.99976',
'C1:0.999592 C2:0.341583'
];
$VAR1 = [
'0.847141',
'0.0438548',
'0.21728',
'0.9452',
'0.999592',
'0.341583'
];
这非常有效,为每种情况输出较小的“q值”。但是,将@_
替换为$#_
也可以。
这种方法也是如此:
foreach (@intersect) {
chomp;
@q_value1 = ($_ =~ /C1:.*?q:(\d+\.\d+)/);
@q_value2 = ($_ =~ /C2:.*?q:(\d+\.\d+)/);
push @q_values, "C1:@q_value1\tC2:@q_value2";
my $q_value1 = $q_value1[0] // $q_value1[1];
my $q_value2 = $q_value2[0] // $q_value2[1];
if (abs $q_value1 < abs $q_value2) {
push @change_q, $q_value1;
}
elsif (abs $q_value2 < abs $q_value1) {
push @change_q, $q_value2;
}
}
print Dumper (\@q_values);
print Dumper (\@change_q);
输出:
$VAR1 = [
'C1:0.847141 C2:0.967194',
'C1:0.999592 C2:0.0438548',
'C1:0.21728 C2:0.99976',
'C1:0.999592 C2:0.9452',
'C1:0.999592 C2:0.99976',
'C1:0.999592 C2:0.341583'
];
$VAR1 = [
'0.847141',
'0.0438548',
'0.21728',
'0.9452',
'0.999592',
'0.341583'
答案 0 :(得分:5)
“这完美无缺”让它变得有点强大。巧合的是,这将是一个更好的描述。您正在使用@_
数组,其最高索引$#_
和数字零,每次都得到相同的结果。你没有意识到的是@_
实际上是空的,因为它只在将参数传递给子程序时使用。所以当你说
$foo[@_]
你真的在说
$foo[0]
当你说
时$foo[$#_]
你真的在说
$foo[-1]
为了额外的乐趣,-1
也是一个有效的数组元素,意味着数组中的最后一个元素,因此对于大小为1或2的数组,它似乎可能正常工作。
因为在标量上下文中,数组@_
将返回其大小,在本例中为0
。当$#_
为空时,-1
将返回@_
,因为没有最高索引。
所以,回答你的问题:因为使用@_
是错误的并且仅在事故中起作用,使用固定数字0
和1
是更好的解决方案。