Я хотел получить фрукты и информацию из входного файла по порядку (чтение с первой строки и далее). Приведенный ниже код каким-то образом печатает фрукты и информацию в любом случайном порядке, каждый раз при запуске скрипта генерируется другой порядок, а не чтение с первой строки. Любая рекомендация?
У меня есть входной файл, как показано ниже
apple
text1
text2
grape
text3
text4
jackfruit
text5
и это код, который я должен вызывать каждый фрукт и информацию
use strict;
use warnings;
my %hash;
open FILE, "config.txt" or die $!;
my $key;
while (my $line = <FILE>) {
chomp($line);
if ($line !~ /^\s/) {
$key = $line;
#$hash{$key} = [];
} else {
$line =~ s/\s//g;
push (@{ $hash{$key} }, $line);
}
}
close FILE;
my %final;
foreach my $fruit (keys %hash){
foreach my $info (values @{$hash{$fruit}}){
print "Fruit: $fruit\n";
print "Info for $fruit = $info\n";
}
}
keys %hash
Дает вам массив ключей из хэша, но не отсортированный. Вы можете отсортировать его с помощью команды sort
Вся линия будет
foreach my $fruit (sort(keys %hash)){
Используйте perldoc -f sort
, чтобы получить помощь по функции сортировки.
print join(" ",sort(keys %{{2 => 3, 1 => 3, 0 => 6}}));
дает 0 1 2
. Для меня я выгляжу правильно
Я думаю, это зависит от того, какой порядок вы хотите. Теперь попробуйте с ключами 1
, 11
, 101
, 2
, 22, and
9`. Но я говорил о том порядке, в котором они появляются в файле, о чем и спрашивал ОП. Хэш этого не делает.
хорошо, вы имеете в виду численную сортировку print join(" ",sort { $a <=> $b}(keys %{{1 => 3, 11 => 3, 101 => 6, 2 => 1, 22 => 1, 9 => 23 }}));
дает 1 2 9 11 22 101
Неа. Я имею в виду вообще не сортировать. Сохраняйте порядок, как показано в файле.
Спасибо, я действительно неправильно понял... омг.
Давайте продолжим обсуждение в чате.
Если вы хотите сохранить порядок вещей в файле, используйте массив. Каждый элемент этого массива может быть хешем, который упорядочивает данные:
#!perl
use v5.26;
my @items;
while( <DATA> ) {
chomp;
if ( /\A(\S+)/ ) {
push @items, { fruit => $1, info => [] }
}
elsif ( /\A\s+(.+)/ ) {
push $items[-1]{info}->@*, $1
}
}
foreach my $item ( @items ) {
print "Fruit: $item->{fruit}\n";
foreach my $info ( $item->{info}->@* ) {
print "\tInfo: $info\n";
}
}
__END__
apple
text1
text2
grape
text3
text4
jackfruit
text5
cranberry
text6
Вывод поддерживает порядок в файле:
Fruit: apple
Info: text1
Info: text2
Fruit: grape
Info: text3
Info: text4
Fruit: jackfruit
Info: text5
Fruit: cranberry
Info: text6
Однако, если вы хотите сохранить их в порядке файла и просто вывести их, вам не нужна структура данных:
my @items;
while( <DATA> ) {
chomp;
if ( /\A(\S+)/ ) {
print "Fruit: $1\n";
}
elsif ( /\A\s+(.+)/ ) {
print "\tInfo: $1\n";
}
}
Если вам нужен немного другой вывод, где каждая строка должна знать фрукт, сохраните это имя в постоянной переменной в цикле while
:
my @items;
while( <DATA> ) {
state $fruit;
chomp;
if ( /\A(\S+)/ ) {
$fruit = $1;
print "Fruit: $fruit\n";
}
elsif ( /\A\s+(.+)/ ) {
print "\t$fruit: $1\n";
}
}
Отличный ответ, я никогда не видел использования @*
, не могли бы объяснить, что он делает.
->@* — постфиксное разыменование.
Это работает только потому, что имена фруктов в примере уже отсортированы по алфавиту, поэтому сортировка хэша по алфавиту дает порядок файлов. Если фрукты в файле не в алфавитном порядке, этот метод не работает.