Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Объединение хэшей


Автор: meridian 16.1.2006, 17:20
Код

Привет всем,
нужна помощь в следующем...

есть %hash_1
(
    "index1" => "имя1, имя2",
    "index2" => "имя2, имя3"
);
есть %hash_2
(
    "index2" => "имя2",
    "index3" => "имя2, имя3",
    "index4" => "имя4"
);

Нужно объеденить хэши без дублей имен

я сделал так, но есть дубли имен

foreach $element ( keys %hash_1 )
{
    $key = $hash_1{ $element };

    if ( $hash_2{ $element } )
    {
        $key1 = $hash_2{ $element };
        $hash_2{ $element } = $key . "," . $key1;
    }    
    else
    {
        $hash_2{ $element } = $key;
    }
}

Спасибо


Автор: korob2001 16.1.2006, 19:39
Попробуй так:
Код

#!/usr/bin/perl -w
use strict;

my %hash1 = ( name1 => "Vasya",
              name2 => "Kolya",
              name3 => "Sasha" );
my %hash2 = ( name2 => "Masha",
              name3 => "Irina",
              name8 => "Valya",
              name9 => "Olya" );

while (my($key,$val) = each %hash2) {
       if (exists $hash1{$key}) {
           $hash1{$key} .= ", $val";
       } else {
           $hash1{$key} = $val;
       }
}

# Теперь покажем содержимое первого хеша
foreach my $key (sort {$a cmp $b} keys %hash1) {
        print "$key => $hash1{$key}\n";
}

Автор: meridian 16.1.2006, 23:04
Код

Спасибо за помощь,
но у меня значения хэшей не по одному значению
my %hash1 = ( name1 => "Vasya",    
              name2 => "Kolya",    
              name3 => "Sasha" );

а именно вот такие
my %hash1 = ( name1 => "Vasya, Masha",    
              name2 => "Kolya",    
              name3 => "Sasha, Viktor, Sergey" );

my %hash2 = ( name1 => "Sveta, Masha",    
              name2 => "Irina",    
              name3 => "Sasha, Olya, Sergey" );



Автор: korob2001 17.1.2006, 06:05
Цитата

но у меня значения хэшей не по одному значению

И что? Всё верно, у тебя значение второго хеша будет добавляться к значению первого, если в первом хеше есть запись с ключём $key, если же её там нет, то будет создан этот ключь и ему просто присваивается новое значение, т.е. $val из второго хеша.
Или тебе нужно что бы в значениях первого хеша не пересекались имена, т.е. что бы добавлялись только те имена, которых в нём нет? Если да, то делай значение в виде анонимного хеша, это даст нам возможность узнать сколько пересекались имена и в то же время они не будут пересечены. О загнул. smile
Код

#!/usr/bin/perl -w
use strict;

my %hash1 = ( name1 => {"Vasya"  => 0,
                        "Masha"  => 0, },
              name2 => {"Kolya"  => 0, },
              name3 => {"Sasha"  => 0,
                        "Viktor" => 0,
                        "Sergey" => 0, } );

my %hash2 = ( name1 => {"Sveta"  => 0,
                        "Masha"  => 0, },
              name2 => {"Irina"  => 0, },
              name3 => {"Sasha"  => 0,
                        "Olya"   => 0,
                        "Sergey" => 0, },
              name8 => {"Valik"  => 0,
                        "Garik"  => 0, }, );

# Объединяем хеши
while ( my($key, $val) = each %hash2 ) {
       for (keys %{$hash2{$key}}) {
            if (exists $hash1{$key}{$_}) {
                ++$hash1{$key}{ucfirst(lc($_))},
            } else {
                $hash1{$key}{ucfirst(lc($_))} = 0;
            }
       }
}

# Теперь выведем всю структуру в STDOUT и покажем сколько раз пересеклись имена,
# а так же сортируем всё сначала по ключам хша %hash1 и по ключам каждого
# анонимного хеша, т.е. по именам.
foreach my $key ( sort {$a cmp $b} keys %hash1 ) {
        print "$key\n";
        foreach my $name ( sort {$a cmp $b} keys %{$hash1{$key}} ) {
                print "\t$name => Кол-во пересечений: " . $hash1{$key}{$name} . "\n";
        }
}

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

Модератор: захватывай в теги "код", только код и коментарии, а просто текст пиши за их пределами. Очень не удобно читать, когда текст сообщения написан вперемешку с кодом.

Автор: meridian 17.1.2006, 10:56
Спасибо, так и есть, нужно чтобы имена не пересекались для каждого тега

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)