Perl 让这变得非常简单,但 Ruby 没有哈希切片,所以我们必须以更迂回的方式来做:
hash = {:one=>1, :two=>2, :three=>3, :four=>4 }
new_key_order = [:one, :three, :two, :four]
new_hash = Hash[new_key_order.zip(hash.values)]
# => {:one=>1, :three=>2, :two=>3, :four=>4}
这是可行的,因为 Ruby 会记住散列的插入顺序,因此 values 总是以原始顺序返回它们。如果您想在不依赖插入顺序的情况下执行此操作,只需稍作改动:
old_key_order = [:one, :two, :three, :four]
new_key_order = [:one, :three, :two, :four]
new_hash = Hash[new_key_order.zip(hash.values_at(*old_key_order))]
# => {:one=>1, :three=>2, :two=>3, :four=>4}
请注意,我对齐了键列以使更改的内容真正突出。这是我们在团队中所做的事情,以帮助在看起来非常相似的代码发生变化时使事情变得明显。
可以使用并行赋值,但是当您处理大量列或字段时,这会很快导致代码混乱。 定义输入顺序和输出顺序更容易,就像上面一样,所以你对映射有一个非常直观的引用,然后将它们传递给 zip 并让它完成艰苦的工作,然后将其强制回哈希。
顺便说一句,这是我在 Perl 中的做法。这是使用调试器:
perl -de 1
DB<1> %hash = ('one' => 1, 'two' => 2, 'three' => 3, 'four' => 4)
DB<2> x \%hash
0 HASH(0x7fceb94afce8)
'four' => 4
'one' => 1
'three' => 3
'two' => 2
DB<3> @hash{'one', 'three', 'two', 'four'} = @hash{'one', 'two', 'three', 'four'}
DB<4> x \%hash
0 HASH(0x7fceb94afce8)
'four' => 4
'one' => 1
'three' => 2
'two' => 3
基本上,Perl 具有检索或分配与 Ruby 的 values_at 等效的能力,方法是将哈希强制转换为数组并定义键的顺序。当您想要重组大量数据时,它是 Perl 中一个非常强大的工具。