【问题标题】:How to alter the hash values with new values in perl?如何用 perl 中的新值更改哈希值?
【发布时间】:2015-01-26 07:49:56
【问题描述】:

如何在 perl 中重置哈希值

use warnings;
use strict;
my %hash = qw(one 1 two 2 three 3 four 4);
my @key = keys(%hash);
my @avz = (9..12);
my %vzm;
print "Original hash and keys : ",%hash,"\n";
for(my $i = 0; $i<=scalar @avz; $i++){
    my @new = "$key[$i] $avz[$i] ";
    push(%vzm , @new);
}
print "modified hash and keys",%vzm,"\n";

我试图用另一个键更改原始哈希的键。我该怎么做 这个程序给出的错误是:

 Original hash and keys : three3one1two2four4
 Not an ARRAY reference at key.pl line 10.

我希望输出是

 Original hash and keys : three3one1two2four4
 modified hash and keys : three11one9two10four12

我该怎么做

【问题讨论】:

标签: perl data-structures hash


【解决方案1】:

好的,首先 - 你在代码中做了一些讨厌的事情:

您正在尝试采用有序的数据结构 - 一个数组 - 并将其推送到一个键控数据结构中,该结构没有定义特定的顺序。

这不会很好地工作——它在技术上是有效的,因为 perl 在内部以类似的方式处理数组和哈希。

但例如你的第一个任务 - 你实际上得到的是:

my %hash = (
    one   => 1,
    two   => 2,
    three => 3,
    four  => 4
);

您可以通过keys() 访问密钥(无特定顺序)。以及来自values() 的值。但是尝试将其视为数组是未定义的行为。

向数组中添加元素:

$hash{'nine'} = 9;

从数组中删除元素:

delete ( $hash{'one'} ); 

您可以迭代 keysvalues - 并结合 sort 甚至以某种顺序执行它们。 (请记住对字母数字进行排序,您将有一个自定义排序作业)。

 foreach my $key ( sort keys %hash ) { 
    print "$key => $hash{$key}\n";
 }

(注意 - 这是按字母数字字符串排序,所以给出:

four => 4
one => 1
three => 3
two => 2

如果要按值排序:

 foreach my $key ( sort { $hash{$a} <=> $hash{$b} } keys %hash ) { 
    print "$key => $hash{$key}\n";
 }

所以你会得到:

one => 1
two => 2
three => 3
four => 4

所以真正的问题仍然存在 - 您实际上想要完成什么?散列的 point 是为您提供一个无序的键值对小型数据库。将一个像数组一样对待并没有多大意义。要么您以任意顺序迭代哈希元素,要么您正在对其应用特定排序 - 但是您依赖于以特定顺序获取元素的计划是一个糟糕的计划 - 它可能有效,但它不是 保证可以工作,这会导致糟糕的代码。

【讨论】:

  • ++ 有人曾经告诉我,当您考虑数据并以假设数据集的某些元素出现在其他元素之前或之后的方式访问数据时 - 您在想的数组。当您考虑数据并通过引用数据集部分的命名方案来访问它时 - 您正在考虑哈希。这似乎很明显,但关键(不是双关语)是仔细考虑数据及其结构如何影响您使用它的方式。
  • 确实如此。数组和哈希可能看起来很相似,并且具有相似的结构,但它们都是关于数据模型的。我仍然认为哈希是 Perl 最大的“卖点”之一——很多语言都可以做数组
【解决方案2】:

您必须保持某个数组中键的顺序,或者从原始列表中获取它

my @tmp = qw(one 1 two 2 three 3 four 4);
my %hash = @tmp;
# 'one', 'two', ..
my @key = @tmp[ grep !($_%2), 0 .. $#tmp ];


# ..
for my $i (0 .. $#avz) {

  $vzm{ $key[$i] } = $avz[$i];
}

或者使用散列切片作为更糟糕的方法,

@vzm{ @key } = @avz;

【讨论】:

  • 我希望输出是three11one9two10four12
【解决方案3】:

如果不单独跟踪该顺序,您将无法做您想做的事情(按照最初添加的顺序替换散列中键的值),因为散列没有任何特定的顺序。换句话说,这是:

my @key = keys(%hash);

必须是这样的:

my @key = ( 'one', 'two', 'three', 'four' );

一旦你有了它,你就可以使用散列片一次性分配所有值:

my %vzm;
@vzm{@key} = @avz;

【讨论】:

    【解决方案4】:

    要创建一个哈希元素,您可以使用$var{$key} 的赋值。

    for (my $i = 0; $i < scalar @avz; $i++) {
        $vzm{$key[$i]} = $avz[$i];
    }
    

    还要注意循环条件应该是&lt;,而不是&lt;=。列表/数组索引以 scalar @avz - 1 结尾。

    【讨论】:

    • 它给出了三个9one10two11four12
    • 散列中键的顺序是任意的。看看Original hash and keys中的顺序。
    • 我希望输出是three11one9two10four12
    • 为什么会这样?键的顺序与原始哈希相同,值的顺序来自@avz 列表。
    猜你喜欢
    • 2014-04-13
    • 2012-04-27
    • 1970-01-01
    • 2021-06-01
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    相关资源
    最近更新 更多