复制哈希数组中前N个键和值

4

我有一个数组的哈希表。

%HoA = (
    'C1' =>  ['1', '3', '3', '3'],
    'C2' => ['3','2'],
    'C3' => ['1','3','3','4','5','5'],
    'C4'  => ['3','3','4'],
    'C5' => ['1'],
);

我希望编写一个子程序,返回一个“子拷贝”数组哈希表,其中包含原始数组哈希表中前N个键(及其值)。类似于以下内容:
my %HoA2 = new_partition(\%HoA, 3);

它会返回一个新的哈希数组数据结构:

%HoA = (
    'C1' =>  ['1', '3', '3', '3'],
    'C2' => ['3','2'],
    'C3' => ['1','3','3','4','5','5'],
 );

有没有一种方法可以在不使用模块的情况下从头开始实现这个功能?
2个回答

3

由于哈希键的顺序未定义,因此不存在“前N个元素”,不能依赖它们。

如果您想要任意三个元素而不是前三个,请使用

%HoA = @HoA{ ( keys %HoA )[0..2] };

好的,我只是想知道这是否可能。在我遭受批评之前,我应该删除我的问题。 - cooldood3490
4
不可能并不意味着这是一个糟糕的问题。将来可能会有其他人需要相同的答案。没有必要删除它。 - jwueller
你可以使用保留添加键的顺序的哈希表。请参见:https://metacpan.org/module/Tie::IxHash - ugexe
1
添加了一个代码片段,可以获取任意三个元素(而不仅仅是前三个)。 - ikegami

3

正如所述,哈希中元素的顺序是不确定的。但是,如果您可以对元素施加自己的顺序,则很容易提取所需的元素:

my %HoA = (
    'C1' => ['1', '3', '3', '3'],
    'C2' => ['3','2'],
    'C3' => ['1','3','3','4','5','5'],
    'C4' => ['3','3','4'],
    'C5' => ['1'],
);

# Use an array slice to grab the first 3 keys from a sorted list of %HoA keys.
# Use map to create a new hash that contains the keys and the values from the
# original hash:
my %HoA2 = map { $_ => $HoA{$_} } (sort keys %HoA)[0..2];

# Alternatively, specify the exact keys that you require:
my %HoA3 = map { $_ => $HoA{$_} } qw(C1 C2 C3);

# { C1 => [1, 3, 3, 3], C2 => [3, 2], C3 => [1, 3, 3, 4, 5, 5] }

更新

正如Borodin所指出的那样,上述方法会复制引用,因此对一个哈希表的更改会反映在另一个哈希表中:

push @{$HoA{C1}}, 9;

# %HoA2 and %HoA3:
# { C1 => [1, 3, 3, 3, 9], C2 => [3, 2], C3 => [1, 3, 3, 4, 5, 5] }

为了避免这种情况,复制数组本身:
my %HoA4 = map { $_ => [@{ $HoA{$_} }] } qw(C1 C2 C3);

2
这可能是想要的,但它复制了数组引用,因此如果新哈希中的数据被修改,更改也将反映在旧哈希中。为了复制数组,可以改用 my %HoA3 = map { $_ => [@{ $HoA{$_} }] } qw(C1 C2 C3) - Borodin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接