Вопрос по hash, perl – объединить хеш-значения, когда ключ одинаков в Perl

2

У меня есть хэш что-то вроде :

abc=>1
hello=>32
abc=>4
hello=>23
hello=>12
xyz=>18

как мы можем объединить значения, ключи которых одинаковы. Таким образом, результат будет:

abc=>"1,4"
hello=>"23,12,32"
xyz=>"18".

Я попытался отсортировать хэш по ключам, а затем проверить для каждого ключа, если они одинаковы, затем объединить значение, но я не понимаю, как сравнить два ключа в одном цикле.

Заранее спасибо.

Это похоже на пары ключ-значение, а не на хеш, поскольку хэш всегда имеет ровно одно значение, связанное с одним ключом. Oleg V. Volkov
Как вы можете иметь хэш с такими же ключами? Вы имеете в виду массив сkey => value пары? Qtax
Да, я ошибаюсь, задавая свой вопрос, это не хеш, а пара ключ-значение. я прошу прощения за это, rahul
Для хэша Perl невозможно иметь два элемента с одинаковым ключом. Пожалуйста, опишите вашу основную проблему. Borodin

Ваш Ответ

4   ответа
1
my @pairs = (
    abc=>1,
    hello=>32,
    abc=>4,
    hello=>23,
    hello=>12,
    xyz=>18,
);

my %hash;

# collect
for(my $idx = 0; $idx < scalar @pairs; $idx += 2){
    my $key = $pairs[$idx];
    my $val = $pairs[$idx+1];
    push @{ $hash{$key} }, $val;
}

# print combined
while( my ($key, $val) = each %hash ){
    print "$key = ", join(',', @$val), "\n";
}
7

которым это работает, зависит от реального источника ваших данных, но эта программа показывает способ чтения информации изDATA Файловый дескриптор для создания и сброса хэша.

Значения хеша являются анонимными массивами, которые содержат все значения, соответствующие одному и тому же ключу.

use strict;
use warnings;

my %data;

while (<DATA>) {
  my ($k, $v) = /\w+/g;
  push @{ $data{$k} }, $v;
}

for my $k (sort keys %data) {
  printf "%s => %s\n", $k, join ',', @{ $data{$k} };
}

__DATA__
abc=>1
hello=>32
abc=>4
hello=>23
hello=>12
xyz=>18

output

abc => 1,4
hello => 32,23,12
xyz => 18
+1, не знал, что вы можете нажать на неопределенную ссылку, подобную этой.
спасибо @Borodin, этот подход работал для меня rahul
3

о которых вы говорите, то вы можете сделать что-то вроде:

my @kv = (
    abc=>1,
    hello=>32,
    abc=>4,
    hello=>23,
    hello=>12,
    xyz=>18,
);

my %hash;

while(@kv){
    my $k = shift @kv;
    my $v = shift @kv;

    $hash{$k} = defined $hash{$k} ? "$hash{$k},$v" : $v;
}
0

что вы на самом деле пытаетесь сделать, я предполагаю, что у вас есть файл, который нужно изменить. В этом случае однострочник может быть в порядке.

perl -lwne '
    ($k,$v) = split /=>/; 
    $data{$k} = join ",", $data{$k} // (), $v }{ 
    print "$_=>$data{$_}" for keys %data' input.txt > output.txt

Output:

hello=>32,23,12
abc=>1,4
xyz=>18

Обратите внимание, что ключи в выходных данных не будут в том же порядке, что и входные. Вы можете сортировать ключи, если хотите, но я решил не делать этого.

Объяснение:

-l will remove line endings while reading, and put them back while printing -n will place a while(<>) loop around the program, reading the file (or STDIN) line by line. // is the defined-or operator. It will return the RHS if the LHS is undefined. }{ is the eskimo kiss operator which only works with the -n option. What it does is basically the same as an END block, it performs the following code at the end of the input.
@rahul Что это я слышу о строке 90? Вы вставили это в какой-то другой программный файл или что-то?
Привет TLP, я попытался запустить этот код, но это выдает ошибку вроде: Строка найдена там, где ожидается оператор рядомprint "$_=>$Rhash{$_}" for keys %Rhash'   (Может быть строка из бегущей многострочной «строки», начинающейся со строки 90) (Отсутствует точка с запятой в предыдущей строке?) Скаляр найден там, где ожидается операторprint "$_=>$Rhash{$_}" for keys %Rhash', Я пытался исправить это, но не могу, поскольку я не очень хорошо знаком с Perl one-liner. Если вы думаете, что я делаю какую-то ошибку, или вы знаете об этой ошибке, пожалуйста, сообщите мне. заранее спасибо rahul

Похожие вопросы