迭代一个简单的程序
我有以下文件:迭代一个简单的程序
a b 5
c d 6
e f 7
g h 4
i j 3
k l 10
和我想找到哪一行呈现最小值在第三列和从初始文件擦除。在此之后,我想再次迭代该程序,并再次找到哪一行呈现最小值,并再次进行2次相同的操作。
输出文件应该是
c d 6
e f 7
k l 10
我试着写了下面的代码:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $file1 = "try.dat";
open my $fg, "<", $file1 or die "Error during $file1 opening: $!";
my @vector;
while (<$fg>) {
push @vector, [ split ];
}
my $minimum = $vector[0][2];
my @blacklist;
for my $i (0 .. $#vector) {
if ($minimum > $vector[$i][2]){
$minimum = $vector[$i][2];
push @blacklist, @vector[$i+1];
}
}
#say "my minimum is $minimum";
#say "the blacklist is composed by @blacklist";
我不知道如何以擦除首先由@blacklist
(包含的元素案例应该是i j 3
)以及如何迭代一切。
迭代的任何帮助?
当你说@blacklist = @vector
你正在将整个@vector
数组添加到黑名单。你可能想要做一个push @blacklist, $vector[$i]
。这会将数组引用推入黑名单。
现在,黑名单中有一个数组ref,所以你必须遵守它来打印它。
say "the blacklist is composed by @{$blacklist[0]}";
编辑:对于迭代和写作:
我会跳过@blacklist
阵列(除非你需要它别的东西),并从@vector
删除最小值。然后你可以写@vector
到某个文件。
my $num_elts_to_remove = 3;
for (my $j = 0; $j < $num_elts_to_remove; $j++) {
my $minimum = $vector[0][2];
my $min_idx = 0;
for my $i (0 .. $#vector) {
if ($minimum > $vector[$i][2]){
$minimum = $vector[$i][2];
$min_idx = $i;
}
}
push @blacklist, $vector[$min_index];
splice @vector, $min_idx, 1; #remove array with smallest value
}
现在阵列写入一个文件
open OUT, ">", $outfile or die "Error: $!";
foreach(@vector) {
print OUT join " ", @$_;
print OUT "\n";
}
close(OUT);
打印:
c d 6
e f 7
k l 10
这样的事情是什么Tie::File
被造的。它允许您通过修改绑定数组来修改文件。
这个程序做你想做的。帮助函数minidx
返回保存最小值的传递数组元素的第一个索引。
该程序的工作原理是将文件记录的第三个字段复制到数组@field3
中,并找到那里最小值的索引。然后使用splice
从该文件和@field3
中删除该索引处的元素。
use strict;
use warnings;
use Tie::File;
tie my @file, 'Tie::File', 'file.txt' or die $!;
my @field3 = map { (split)[2] } @file;
for (1 .. 3) {
my $i = minidx(\@field3);
splice @file, $i, 1;
splice @field3, $i, 1;
}
sub minidx {
my ($arr) = @_;
my ($i, $v);
for (0 .. $#$arr) {
($i, $v) = ($_, $arr->[$_]) unless defined $v and $arr->[$_] >= $v;
}
return $i;
}
输出
c d 6
e f 7
k l 10
我可以帮你解决你的问题。所以很少有人喜欢Tie :: File,所以我想你可能也会喜欢我的回答,它会在引擎盖下使用它。 – 2013-03-16 03:54:13
以鲍罗廷的领带::文件建议更进一步。我写了一个名为Tie::Array::CSV的可爱模块,它允许你将一个分隔文件当作一个数组来处理(因为它在下面使用Tie :: File,它是可读写的)。正因为如此,我可以用Perl化的操作,如地图和排序(和使用Schwartzian变换!)来执行此任务:
#!/usr/bin/env perl
use strict;
use warnings;
use Tie::Array::CSV;
tie my @data, 'Tie::Array::CSV', 'data', sep_char => ' ';
# get a list of row ids sorted by last value (inc)
my $i = 0;
my @sorted =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [$i++, $_->[-1]] }
@data;
#splice the rows by index of the lowest three (from bottom to top)
splice @data, $_, 1 for reverse sort @sorted[0..2];
注意,你到底想从底部删除行,这样你就不必每次重新索引。
你应该编辑推'@blacklist,$ vector [$ i + 1]'并且它可以工作。关于如何擦除文件中的行并迭代它的任何想法? – 2013-03-14 17:26:01
在'splice @vector,$ min_idx,1;'这一行是什么意思?如果我想使用“黑名单”数组,我该怎么办?如果($ minimum> $ vector [$ i] [2]){\ i = 0 [$ i] [2]),我尝试了'为我的$ i(0.. $#向量){0}。 push @blacklist,@vector [$ i + 1]; } } splice @vector,@blacklist;'但它不起作用 – 2013-03-15 08:45:48
'1'是长度或要移除的元素的数量。请参阅[文档](http://perldoc.perl.org/functions/splice.html)。如果你想保留一个黑名单,在拼接前先推它。 (见编辑)。 'push @blacklist,$ vector [$ min_index];' – Nate 2013-03-16 02:51:10