Re: I want to operate on some values in a hash
by Eily (Monsignor) on Jan 04, 2018 at 16:15 UTC
|
I'm averse to for ()
Why? The intended meaning of map is to create a new list from an old one. So modifying a set of values with map (rather than create a new set) is considered bad practice. You might do @h{@k} = map { stuff($_) } @h{@k} if you really want to avoid a for loop, or s/stuff/other/ for @h{@k}; if it's having multiple lines that bothers you.
Edit: when I say that modifying a set of values with map is considered bad practice, I'm talking about the inplace modification of elements, as in map { $_ += 2 } @numbers;, (or the dreaded "map in void context"). @h{@k} = map { stuff($_) } @h{@k} isn't as bad, as it actually builds a temporary new list, before overwriting the values in the hash. It's just neither the most straightforward way, nor the usual way. But as long as there's no inplace editing, that's fine IMHO.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
I agree with Eily that using map for in-place modification is bad practice.
I think you could just use filter & map to produce newly generated hash.
my %modified_hash = map { $_ => f($hash{$_})
grep { condition_on_key($_) } keys(%hash);
Edit: s/list/hash/ | [reply] [Watch: Dir/Any] [d/l] |
|
Eily:
" modifying a set of values with map (rather than create a new set) is considered bad practice"
I'd actually never read that, can you elaborate? I often do that with great success. But if there are side-effects or dangers I'm not aware of I'd like to know that..
Thanks
| [reply] [Watch: Dir/Any] |
|
I suppose you wrote that before I edited my message?
Honestly I can't remember seeing the map in void context for a while, except when I mention that people keep bringing up the subject myself (but I did see it often in my earlier readings on perlmonks), make of that what you will.
One reason for the discussion is that map is supposed to build a new list, and not using that output is a waste of resources. But even if map wasn't smart about its context, it's perl, you're supposed to ignore performance issues most of the time and focus on getting things done. The other issue is when you use the aliasing mechanism, ie the fact that modifying $_ will modify the input. Since ; map { $_ += 2 } @numbers; and ; $_ += 2 for @numbers; do exactly the same thing, it's clearer if you use the version that's not supposed to create a separate output. Best reason to use the second version is that you won't get told that there's a better way to do it when you post it on perlmonks :D
NB: even without using the aliasing mechanism: ; map { $h{$_}++} @keys; may be better written as ; $h{$_}++ for @keys;, because map does something from the input, while for does something with the input. Nitpicking at its finest :)
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: I want to operate on some values in a hash
by choroba (Cardinal) on Jan 04, 2018 at 18:02 UTC
|
s/stuff/other stuff/ for @h{ grep /something/, keys %h }
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: I want to operate on some values in a hash
by AnomalousMonk (Archbishop) on Jan 04, 2018 at 18:30 UTC
|
c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le
"my %h = qw(foo oofzle bar rabzle quux xuuqzle fee eefzle);
dd \%h;
;;
my @k = grep m{ foo | bar }xms, keys %h;
;;
map s/zle/DING/, @h{ @k };
dd \%h;
"
{ bar => "rabzle", fee => "eefzle", foo => "oofzle", quux => "xuuqzle"
+ }
{ bar => "rabDING", fee => "eefzle", foo => "oofDING", quux => "xuuqzl
+e" }
Although I have to say I don't understand your general for-aversion — and map contains an implicit loop!
Update: Small change to example code to make it closer to structure of OPed pseudo-code.
Give a man a fish: <%-{-{-{-<
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: I want to operate on some values in a hash
by thanos1983 (Parson) on Jan 04, 2018 at 16:19 UTC
|
Hello misterperl,
Why not simply rename the key on the flow?
Sample of code:
Update: For multiple keys you can use hash slice:
Update2: Update the keys with for loop:
Update3: Also with map (I think this is slower):
Hope this helps, BR.
Seeking for Perl wisdom...on the process of learning...not there...yet!
| [reply] [Watch: Dir/Any] [d/l] [select] |