/ / Tablica skrótów - perl, hash

Tablica skrótów - perl, hash

W Perlu, mam szereg skrótów lubić

0  HASH(0x98335e0)
"title" => 1177
"author" => "ABC"
"quantity" => "-100"


1  HASH(0x832a9f0)
"title" => 1177
"author" => "ABC"
"quantity" => "100"

2  HASH(0x98335e0)
"title" => 1127
"author" => "DEF"
"quantity" => "5100"


3  HASH(0x832a9f0)
"title" => 1277
"author" => "XYZ"
"quantity" => "1030"

Teraz muszę zgromadzić ilość w tytulea autor jest taki sam. W powyższej strukturze dla skrótu z tytułem = 1177 i autor = "ABC" ilość może zostać zebrana w jedną, a cała struktura powinna wyglądać jak poniżej

0  HASH(0x98335e0)
"title" => 1177
"author" => "ABC"
"quantity" => 0

1  HASH(0x98335e0)
"title" => 1127
"author" => "DEF"
"quantity" => "5100"

2  HASH(0x832a9f0)
"title" => 1277
"author" => "XYZ"
"quantity" => "1030"

Jaki jest najlepszy sposób na zrobienie tej akumulacjidzięki czemu jest zoptymalizowany? Liczba elementów tablicy może być bardzo duża. Nie mam nic przeciwko dodaniu dodatkowego klucza do mieszania, aby pomóc to samo, ale nie chcę n wyszukiwania. Uprzejmie poradzę

Odpowiedzi:

4 dla odpowiedzi № 1
my %sum;
for (@a) {
$sum{ $_->{author} }{ $_->{title} } += $_->{quantity};
}

my @accumulated;
foreach my $author (keys %sum) {
foreach my $title (keys %{ $sum{$author} }) {
push @accumulated => { title    => $title,
author   => $author,
quantity => $sum{$author}{$title},
};
}
}

Nie jestem pewien, czy map sprawia, że ​​wygląda ładniej:

my @accumulated =
map {
my $author = $_;
map { author   => $author,
title    => $_,
quantity => $sum{$author}{$_},
},
keys %{ $sum{$author} };
}
keys %sum;

1 dla odpowiedzi nr 2

Jeśli nie chcesz N wyszukiwań, to potrzebujesz haszysz funkcja - jakkolwiek musisz sklep je z tą funkcją skrótu. Do czasu, gdy masz je na liście (lub tablicy), jest za późno. cały czaslub będziesz mieć N wyszukiwań.

Lub wstawić ich do hasza powyżejponiżej. Rozwiązaniem hybrydowym jest przechowywanie lokalizatora jako pozycji 0 na liście / tablicy.

my $lot = get_lot_from_whatever();
my $tot = $list[0]{ $lot->{author} }{ $lot->{title} };
if ( $tot ) {
$tot->{quantity} += $lot->{quantity};
}
else {
push @list, $list[0]{ $lot->{author} }{ $lot->{title} } = $lot;
}

poprzedni

Przede wszystkim zmienimy to, aby było czytelne.

[ { title => 1177, author => "ABC", quantity => "-100" }
, { title => 1177, author => "ABC", quantity => "100"  }
, { title => 1127, author => "DEF", quantity => "5100" }
, { title => 1277, author => "XYZ", quantity => "1030" }
]

Następnie musisz zlikwidować problem. Chcesz ilości zgrupowanych rzeczy według autora i tytułu. Więc potrzebujesz tych rzeczy wyjątkowo zidentyfikować te partie. Aby powtórzyć, chcesz kombinację nazwy do identyfikacji podmioty. Tak więc ty będzie potrzebował skrótu, który identyfikuje rzeczy według nazw.

Ponieważ mamy dwie rzeczy, podwójny hasz to dobry sposób na zrobienie tego.

my %hash;
foreach my $lot ( @list ) {
$hash{ $lot->{author} }{ $lot->{title} } += $lot->{quantity};
}
# consolidated by hash

Aby zmienić to z powrotem na listę, musimy rozdzielić poziomy.

my @consol
= sort { $a->{author} cmp $b->{author} || $a->{title} cmp $b->{title} }
map  {
my ( $a, $titles ) = @$_; # $_ is [ $a, {...} ]
map { +{ title => $_, author => $a, quantity => $titles->{$_} }
keys %$titles;
}
map  { [ $_ => $hash{$_} ] } # group and freeze a pair
keys %hash
;

# consolidated in a list.

I tam go masz, posortowałem nawet dla ciebie. Oczywiście możesz też posortuj to według - wydawców będących tym, czym są - malejącymi ilościami.

sort {  $b->{quantity} <=> $a->{quantity}
|| $a->{author}   cmp $b->{author}
|| $a->{title}    cmp $b->{title}
}

0 dla odpowiedzi № 3

Uważam, że ważne jest, aby się cofnąć i rozważyćźródło danych. Jeśli dane pochodzą z bazy danych, powinieneś napisać kwerendę SQL, aby podać jeden wiersz dla każdej kombinacji autor / tytuł z całkowitą ilością w polu ilości. Jeśli czytasz dane z pliku, powinieneś albo przeczytać je bezpośrednio w haszyszu, albo użyć Tie :: IxHash jeśli zamówienie jest ważne.

Gdy masz dane w tablicy hashrefówtak jak ty, będziesz musiał stworzyć pomocniczą strukturę danych i wykonać całą garść wyszukiwań, których koszt może zdominować czas działania twojego programu (nie w sensie, jeśli jest uruchamiany przez 15 minut po dzień) i możesz napotkać problemy z pamięcią.