簡體   English   中英

當我打印Perl哈希時,什么決定了鍵的順序?

[英]What decides the order of keys when I print a Perl hash?

基於activePerl 5.8

#!C:\Perl\bin\perl.exe
use strict;
use warnings;

# declare a new hash
my %some_hash;

%some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello",
      "wilma", 1.72e30, "betty", "bye\n");

my @any_array;
@any_array = %some_hash;

print %some_hash;
print "\n";
print @any_array;
print "\n";
print $any_array[0];
print "\n";
print $any_array[1];
print "\n";
print $any_array[2];
print "\n";
print $any_array[3];
print "\n";
print $any_array[4];
print "\n";
print $any_array[5];
print "\n";
print $any_array[6];
print "\n";
print $any_array[7];
print "\n";
print $any_array[8];
print "\n";
print $any_array[9];

這樣輸出

D:\learning\perl>test.pl
bettybye
bar12.4wilma1.72e+030foo352.5hello
bettybye
bar12.4wilma1.72e+030foo352.5hello
betty
bye

bar
12.4
wilma
1.72e+030
foo
35
2.5
hello
D:\learning\perl>

是什么決定了示例代碼中元素的打印順序?

在Perl中打印混合(字符串,數字)哈希時要遵循的任何規則? 謝謝。

bar12.4wilma1.72e+030foo352.5hello

[更新]

在你們的幫助下,我更新了以下代碼。

#!C:\Perl\bin\perl.exe
use strict;
use warnings;

# declare a new hash
my %some_hash;

%some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello",
      "wilma", 1.72e30, "betty", "bye");

my @any_array;
@any_array = %some_hash;

print %some_hash;
print "\n";
print "\n";
print @any_array;
print "\n";
print "\n";

my @keys;
@keys = keys %some_hash;
for my $k (sort @keys)
{
    print $k, $some_hash{$k};
}

輸出

D:\learning\perl>test.pl
bettybyebar12.4wilma1.72e+030foo352.5hello

bettybyebar12.4wilma1.72e+030foo352.5hello

2.5hellobar12.4bettybyefoo35wilma1.72e+030
D:\learning\perl>

最后,在調用keyssort函數之后。 按以下規則打印哈希鍵

2.5hellobar12.4bettybyefoo35wilma1.72e+030

哈希的元素以其內部順序打印出來,無法依賴,並且會隨着元素的添加和刪除而發生變化。 如果您需要某種順序的哈希值的所有元素,請對鍵進行排序,然后使用該列表為哈希值編制索引。

如果要查找按順序保留其元素的結構,請使用數組或在CPAN上使用有序哈希之一。

您可以從列表上下文哈希擴展中依賴的唯一順序是鍵=>值對將在一起。

perldoc -f鍵

哈希鍵顯然是隨機順序返回的。 實際的隨機順序在Perl的未來版本中可能會發生變化,但是可以保證與值或每個函數產生的順序相同(假定哈希值未修改)。 從Perl 5.8.1開始,出於安全原因,即使在不同的Perl運行之間,順序也有所不同(請參閱perlsec中的算法復雜性攻擊 )。

...

Perl從未保證哈希鍵的任何順序,並且在Perl 5的生命周期中,該順序已經改變了幾次。而且,哈希鍵的順序始終受插入順序的影響,並將繼續受到其影響。

還要注意,盡管哈希元素的順序可能是隨機的,但這種“偽排序”不應用於諸如隨機排序列表之類的應用(為此,請使用List :: Util :: shuffle(),請參見List :: Util ,從Perl 5.8.0開始的標准核心模塊;或CPAN模塊Algorithm :: Numerical :: Shuffle ),或用於生成置換(例如使用CPAN模塊Algorithm :: PermuteAlgorithm :: FastPermute ),或用於任何加密應用程序。


注意:由於您要在列表上下文中評估哈希, 因此至少可以確保每個鍵后面都帶有對應的值; 例如,您將永遠不會看到a 4 b 3 c 2 d 1

我仔細閱讀了您的代碼,並做了一些說明,認為對您有所幫助。

use strict;
use warnings;

# declare a new hash and initialize it at the same time
my %some_hash = (
    foo   => 35,       # use the fat-comma or '=>' operator, it quotes the left side
    bar   => 12.4,     
    2.5   => "hello",
    wilma => 1.72e30,
    betty => "bye",    # perl ignores trailing commas, 
                       # the final comma makes adding items to the end of the list less bug prone.
);

my @any_array = %some_hash; # Hash is expanded into a list of key/value pairs.

print "$_ => $some_hash{$_}\n" 
    for keys %some_hash;

print "\n\n",              # You can print multiple newlines in one string.
      "@any_array\n\n";    # print takes a list of things to print.

# In print @foo; @foo is expanded into a list of items to print.  
# There is no separator between the members of @foo in the output.

# However print "@foo"; interpolates @foo into a string. 
# It inserts spaces between the members of the arrays.


# This is the block form of 'for'
for my $k (sort keys %some_hash)
{
    # Interpolating the variables into a string makes it easier to read the output.
    print "$k => $some_hash{$k}\n";
}

哈希通過字符串鍵提供無序訪問數據的功能。

數組提供對有序數據的訪問。 通過使用數字索引可以進行隨機訪問。

如果需要保留一組值的順序,請使用數組。 如果需要通過關聯的名稱查找組的成員,請使用哈希。

如果您需要同時執行這兩種操作,則可以同時使用這兩種結構:

# Keep an array of sorted hash keys.
my @sorted_items = qw( first second third fourth );

# Store the actual data in the hash.
my %item;
@item{ @sorted_items } = 1..4;  # This is called a hash slice.  
                                # It allows you to access a list of hash elements.
                                # This can be a very powerful way to work with hashes.

# random access
print "third => $item{third}\n";


# When you need to access the data in order, iterate over
# the array of sorted hash keys.  Use the keys to access the
# data in the hash.

# ordered access
for my $name ( @sorted_items ) {
    print "$name => $item{$name}\n";
}

在查看您的代碼示例時,我看到了一些您可能需要處理的事情。

  • forwhile類的循環結構如何用於減少重復代碼。
  • 如何使用變量插值

順便說一句,很高興看到您在基礎方面進行工作並提高代碼質量。 這種時間上的投資將得到回報。 保持良好的工作。

元素(幾乎可以肯定)是按照它們在哈希表本身中(內部)出現的順序打印出來的,即基於其鍵的哈希值。

遵循的一般規則是,如果您非常關注順序,則可以使用哈希表以外的其他方法。

哈希不能(有必要)以排序的方式檢索。 如果要對它們進行排序,則必須自己進行:

use strict;
use warnings;

my %hash = ("a" => 1, "b" => 2, "c" => 3, "d" => 4);

for my $i (sort keys %hash) {
    print "$i -> $hash{$i}\n";
}

通過使用鍵從哈希中檢索所有keys ,然后使用sort對其進行sort 是的,我知道,那個瘋狂的拉里·沃爾(Larry Wall)家伙,曾經想過要稱呼他們嗎? :-)

輸出:

a -> 1
b -> 2
c -> 3
d -> 4

對於大多數實際目的,可以將哈希表(不僅是Perl哈希變量,而且通常是哈希表)的順序視為隨機的。

實際上,根據哈希實現方式,順序實際上可能是確定性的。 (即,如果您多次運行該程序,並且每次都以相同的順序將相同的項放入哈希表中,那么它們每次將以相同的順序進行存儲。)我知道Perl哈希曾經具有這種特性,但是我不確定當前版本。 無論如何,在需要隨機性的情況下,哈希鍵順序不是可靠的隨機性來源。

短版,然后:

如果您關心順序(或缺少順序),請不要使用哈希。 如果您想要一個固定的訂單,那么它實際上是隨機的;如果您想要一個隨機的訂單,那么它將會被有效地固定。

哈希沒有定義任何排序屬性。 事物出現的順序將是不可預測的。

而且,如果您發瘋了,並且哈希中沒有重復的值,並且需要對值進行排序,則可以對其調用反向。

my %hash = ("a" => 1, "b" => 2, "c" => 3, "d" => 4);
my %reverse_hash = reverse %hash;

print $_ for sort keys %reverse_hash;

注意是唯一值部分,重復項將被覆蓋,只有一個值會進入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM