在perl中以哈希格式编写交换键和值的最简洁的方法
我想通过在perl中交换散列中的键和值来创建一个新的散列。注意,这样做的目的是将重复值的键放入一个数组中,这与在perl中以哈希格式编写交换键和值的最简洁的方法,perl,Perl,我想通过在perl中交换散列中的键和值来创建一个新的散列。注意,这样做的目的是将重复值的键放入一个数组中,这与reverse所做的不同 很明显,我可以做一个循环。但是我不确定是否可以用一种紧凑的形式,比如使用map等 谢谢。你可以做这样一个“紧凑”的循环 my %orig = # whatever my %rev; push @{$rev{$orig{$_}}}, $_ for keys %orig; 请注意,“反向”散列的所有值都将是具有此功能的数组。是否像这样工作 my %orig = (
reverse
所做的不同
很明显,我可以做一个循环。但是我不确定是否可以用一种紧凑的形式,比如使用map
等
谢谢。你可以做这样一个“紧凑”的循环
my %orig = # whatever
my %rev;
push @{$rev{$orig{$_}}}, $_ for keys %orig;
请注意,“反向”散列的所有值都将是具有此功能的数组。是否像这样工作
my %orig = ( 1 => 'a', 2 => 'b', 3 => 'c', 65 => 'a' );
my $new_hash = List::Util::reduce { push @{ $a->{$orig{$b}} }, $b; $a } {}, keys %orig;
出于某种原因,在散列解引用中包装reduce调用似乎打破了&-prototype的魔力,但您可以通过以下方式避免新变量:
%orig = %{ List::Util::reduce sub { push @{ $a->{$orig{$b}} }, $b; $a }, {}, keys %orig };
如果要避免对%orig的内部引用,请假设原始哈希是来自其他表达式的结果,假设perl具有成对列表:
%orig = %{ List::Util::reduce sub { push @{ $a->{ $b->[0] } }, $b->[1]; $a }, {},
@{ List::Util::reduce sub { ! @$a || $#{ $a->[-1] } ? push @$a, [ $b ] : push @{ $a->[-1] }, $b; $a }, [],
reverse %orig
}
};
具有一些实用功能的更漂亮:
sub flatten_hashref { %{$_[0]} }
sub flatten_arrayref { @{$_[0]} }
sub pairlist { reduce { ! @$a || $#{ $a->[-1] } ? push @$a, [ $b ] : push @{ $a->[-1] }, $b; $a } [], @_ }
%orig =
flatten_hashref
reduce { push @{ $a->{ $b->[0] } }, $b->[1]; $a } {},
flatten_arrayref
pairlist
reverse
%orig;
定义“契约”;然后告诉我们为什么这是一个值得称赞的目标。在我的评分册上,短小且不可读的内容会让你失去分数。@tchrist:我的意思是“更实用”。我相信避免显式循环可以在matlab、R、python以及perl等语言中获得一些效率。也许不是所有的情况,但通常都是这样。我说得对吗?不,不对。如果代码对您更有意义,而不是为了提高效率,请这样做。谢谢。这就是我在循环方法中所说的。我想问的是:我可以一次性声明一个新的散列,还是不显式声明一个新的散列,就像
%orig=map{$orig{$\u}=>$\ u}键(%orig)代码>?我不知道有一个。声明新哈希有什么问题?