重複條目我有兩個數組:perl的 - 數學與陣列
my @name = (bob, bob, dave, john, john, mary, mary, mary);
my @cost = (5, 7, 4, 4, 4, 6, 3 , 4);
我想他們在一起,映射所以輸出將只是:
bob 12
dave 4
john 8
mary 13
陣列的變化,雖然這樣我就可以不使用參考。如何通過@name
將@cost
分組並添加@cost
的值?
重複條目我有兩個數組:perl的 - 數學與陣列
my @name = (bob, bob, dave, john, john, mary, mary, mary);
my @cost = (5, 7, 4, 4, 4, 6, 3 , 4);
我想他們在一起,映射所以輸出將只是:
bob 12
dave 4
john 8
mary 13
陣列的變化,雖然這樣我就可以不使用參考。如何通過@name
將@cost
分組並添加@cost
的值?
我會嘗試這樣的事情。
#!/usr/bin/perl
use strict; use warnings; use Data::Dumper;
my @name = qw(bob bob dave john john mary mary mary);
my @cost = qw(5 7 4 4 4 6 3 4);
my %seen =();
foreach(0..scalar(@name)-1){
if (!exists $seen{$name[$_]}){
$seen{$name[$_]} = $cost[$_];
}
else{
my $sum = 0;
$sum = $seen{$name[$_]};
my $new = $sum + $cost[$_];
$seen{$name[$_]} = $new;
}
}
print Dumper(\%seen);
OUTPUT:
$VAR1 = {
'bob' => 12,
'john' => 8,
'dave' => 4,
'mary' => 13
};
FWIW:我可能會迭代到'$#name'而不是'scalar(@name)-1'。而且,利用autovivification可以讓你放棄'if'子句,並且運行'else'塊中包含的內容。 – tjd
@tjd確實,這樣做會更好,但我更喜歡使用這些簡單的線條有時很難理解某些功能。 – AbhiNickz
當我看到'if(!...){...} else {...}'時,我總感到不舒服。當然,用if/else子句反過來寫就更好了,並且從條件中刪除了'!'。但正如tjd指出的那樣,autovivification意味着你根本不需要檢查。另外,你在某些地方不必要地引用了你的哈希鍵('「$ name [$ _]」'),但是在其他地方不會。這會讓人們感到困惑。 –
像這樣的東西應該工作:
my %myHash =();
for (my $i=0 ; $i<$#name ; $i++) {
$myHash{$name[$i]} += $cost[$i];
}
然後你只需要遍歷數組以得到總成本:
for (keys %myHash) {...}
你可以用一個(在我看來)更容易理解'foreach'循環來替換一個像你一樣的C風格'for'循環。在這種情況下,它會是'foreach my $ i(0.. $#name)' –
@DaveCross True。但是對於SO答案,我傾向於更喜歡經典的「for」,因爲它們更具普遍性/語言不可知性。然而,對於我自己的代碼,任何事情都會發生:) – AntonH
對於SO答案,我更喜歡任何構造使代碼更易於閱讀。這很少是C風格的循環。我發現使用它時很容易發生錯誤的錯誤。 –
一些map掛羊頭賣狗肉:
my %hash;
%hash = map {$name[$_] => $hash{$name[$_]} += $cost[$_]} 0..$#name;
就個人而言,我會用一個for()
或while()
循環的解決方案去不過,因爲它更容易看到一目瞭然。
你想創建一個新的數組與結果或只是打印結果? –
使用散列,將'@ cost'的值添加到'@ name'中的鍵的值。 – AntonH
反正沒問題。我想打印的輸出是''bob'= 12'dave'= 4'等等。現在我只是停留在數學上。 – cflinspach