diff --git a/README b/README index f24465a..8ab9398 100644 --- a/README +++ b/README @@ -15,8 +15,8 @@ SYNOPSIS my $foo = $hash->get('foo'); # 'b' (always, regardless of context) my @foo = $hash->get_all('foo'); # ('a', 'b') - keys %$hash; # ('foo', 'bar') not guaranteed to be ordered - $hash->keys; # ('foo', 'bar') guaranteed to be ordered + keys %$hash; # ('foo', 'bar') not guaranteed to be ordered + $hash->keys; # ('foo', 'foo', 'bar') guaranteed to be ordered DESCRIPTION Hash::MultiValue is an object (and a plain hash reference) that may @@ -109,7 +109,15 @@ METHODS keys @keys = $hash->keys; - Returns a list of keys, in an ordered way. + Returns a list of all keys, including duplicates (see the example in + the "SYNOPSIS"). + + If you want only unique keys, use "keys %$hash", as normal. + + values + @values = $hash->values; + + Returns a list of all values, in the same order as "$hash->keys". add $hash->add($key, $value [, $value ... ]); @@ -133,6 +141,31 @@ METHODS Gets pairs of keys and values. This should be exactly the same pairs which are given to "new" method unless you updated the data. + each + $hash->each($code); + + # e.g. + $hash->each(sub { print "$_[0] = $_[1]\n" }); + + Calls $code once for each "($key, $value)" pair. This is a more + convenient alternative to calling "flatten" and then iterating over + it two items at a time. + + Inside $code, $_ contains the current iteration through the loop, + starting at 0. For example: + + $hash = Hash::MultiValue->new(a => 1, b => 2, c => 3, a => 4); + + $hash->each(sub { print "$_: $_[0] = $_[1]\n" }); + # 0: a = 1 + # 1: b = 2 + # 2: c = 3 + # 3: a = 4 + + Be careful not to change @_ inside your coderef! It will update the + tracking object but not the plain hash. In the future, this + limitation may be removed. + clone $new = $hash->clone; diff --git a/lib/Hash/MultiValue.pm b/lib/Hash/MultiValue.pm index 28c6359..9aaa34b 100644 --- a/lib/Hash/MultiValue.pm +++ b/lib/Hash/MultiValue.pm @@ -127,8 +127,12 @@ sub clone { sub keys { my $self = shift; - my %seen; - grep { !$seen{$_}++ } @{$keys{refaddr $self}}; + return @{$keys{refaddr $self}}; +} + +sub values { + my $self = shift; + return @{$values{refaddr $self}}; } sub flatten { @@ -164,7 +168,7 @@ sub as_hashref_mixed { my %hash; push @{$hash{$k->[$_]}}, $v->[$_] for 0 .. $#$k; - for (values %hash) { + for (CORE::values %hash) { $_ = $_->[0] if 1 == @$_; } @@ -213,8 +217,8 @@ Hash::MultiValue - Store multiple values per key my $foo = $hash->get('foo'); # 'b' (always, regardless of context) my @foo = $hash->get_all('foo'); # ('a', 'b') - keys %$hash; # ('foo', 'bar') not guaranteed to be ordered - $hash->keys; # ('foo', 'bar') guaranteed to be ordered + keys %$hash; # ('foo', 'bar') not guaranteed to be ordered + $hash->keys; # ('foo', 'foo', 'bar') guaranteed to be ordered =head1 DESCRIPTION @@ -320,7 +324,16 @@ attached, the result will be an empty list. @keys = $hash->keys; -Returns a list of keys, in an ordered way. +Returns a list of all keys, including duplicates (see the example in the +L). + +If you want only unique keys, use C<< keys %$hash >>, as normal. + +=item values + + @values = $hash->values; + +Returns a list of all values, in the same order as C<< $hash->keys >>. =item add diff --git a/t/hash.t b/t/hash.t index 66671e9..73db100 100644 --- a/t/hash.t +++ b/t/hash.t @@ -58,6 +58,9 @@ my $hash = Hash::MultiValue->new( [ foo => 'b', foo => 'c', bar => 'bba', baz => 34 ]; is_deeply $hash, { foo => 'b', bar => "baz", baz => 33 }; + + is_deeply [ $hash->keys ], [ qw(foo foo bar baz) ]; + is_deeply [ $hash->values ], [ qw(b c bba 34) ]; } done_testing; diff --git a/t/multi.t b/t/multi.t index 5cf2aba..99651dd 100644 --- a/t/multi.t +++ b/t/multi.t @@ -14,7 +14,7 @@ is ref $hash->{foo}, ''; my @foo = $hash->get_all('foo'); is_deeply \@foo, [ 'a', 'b' ]; is_deeply [ sort keys %$hash ], [ 'bar', 'baz', 'foo' ]; -is_deeply [ $hash->keys ], [ 'foo', 'bar', 'baz' ]; +is_deeply [ $hash->keys ], [ 'foo', 'foo', 'bar', 'baz' ]; is $hash->{baz} + 2, 35; is $hash->get_one('bar'), 'baz';