Ты здесь очень близко.Мы не можем получить именно тот результат, который вы хотите получить от Data::Dumper
, потому что хэши могут иметь только одно значение на ключ.Самый простой способ исправить это - присвоить ключу ссылку на массив и добавить к нему что-нибудь.Но так как вы также хотите исключить дубликаты, проще создать хеши в качестве промежуточного представления, а затем преобразовать их в массивы:
use Data::Dumper;
my $file = "animals.txt";
open($fh, "<", $file) || die "Could not open file $file $!/n";
while (<$fh>) {
chomp;
if(/^>(.+)/){
$group = $1;
next;
}
$animals{$group} = {} unless exists $animals{$group};
$animals{$group}->{$_} = 1;
}
# Transform the hashes to arrays
foreach my $group (keys %animals) {
# Make the hash into an array of its keys
$animals{$group} = [ sort keys %{$animals{$group}} ];
# Throw away the array if we only have one thing
$animals{$group} = $animals{$group}->[0] if @{ $animals{$group} } == 1;
}
print Dumper(\%animals);
Результат равен
$VAR1 = {
'Reptiles' => 'Snakes',
'Fish' => 'Clownfish',
'Birds' => 'Parrots',
'Mammals' => [
'Cats',
'Dogs'
]
};
, который настолько близокпоскольку вы можете получить то, что у вас было в качестве желаемого результата.
Для простоты обработки загруженных данных, на самом деле может быть проще , а не выбрасывать массивы в случае с одним элементомтак что каждая запись в хэше может обрабатываться одинаково (все они являются ссылками на массивы, независимо от того, сколько в них вещей).В противном случае вы добавили условное выражение для удаления массивов, и вам необходимо добавить еще один условный тест в код обработки, чтобы проверить
if (ref $item) {
# This is an anonymous array
} else {
# This is just a single entry
}
, и проще иметь только один путь вместо двух, дажеесли else
просто снова упаковывает один элемент в массив.Оставьте их как массивы (удалите строку $animals{$group} = $animals{$group}->[0]
), и все будет в порядке.