gpt4 book ai didi

perl - 如何在 Perl 中将多个哈希合并为一个哈希?

转载 作者:行者123 更新时间:2023-12-04 14:52:33 25 4
gpt4 key购买 nike

在 Perl 中,我如何得到这个:

$VAR1 = { '999' => { '998' => [ '908', '906', '0', '998', '907' ] } }; 
$VAR1 = { '999' => { '991' => [ '913', '920', '918', '998', '916', '919', '917', '915', '912', '914' ] } };
$VAR1 = { '999' => { '996' => [] } };
$VAR1 = { '999' => { '995' => [] } };
$VAR1 = { '999' => { '994' => [] } };
$VAR1 = { '999' => { '993' => [] } };
$VAR1 = { '999' => { '997' => [ '986', '987', '990', '984', '989', '988' ] } };
$VAR1 = { '995' => { '101' => [] } };
$VAR1 = { '995' => { '102' => [] } };
$VAR1 = { '995' => { '103' => [] } };
$VAR1 = { '995' => { '104' => [] } };
$VAR1 = { '995' => { '105' => [] } };
$VAR1 = { '995' => { '106' => [] } };
$VAR1 = { '995' => { '107' => [] } };
$VAR1 = { '994' => { '910' => [] } };
$VAR1 = { '993' => { '909' => [] } };
$VAR1 = { '993' => { '904' => [] } };
$VAR1 = { '994' => { '985' => [] } };
$VAR1 = { '994' => { '983' => [] } };
$VAR1 = { '993' => { '902' => [] } };
$VAR1 = { '999' => { '992' => [ '905' ] } };

对此:
$VAR1 = { '999:' => [
{ '992' => [ '905' ] },
{ '993' => [
{ '909' => [] },
{ '904' => [] },
{ '902' => [] }
] },
{ '994' => [
{ '910' => [] },
{ '985' => [] },
{ '983' => [] }
] },
{ '995' => [
{ '101' => [] },
{ '102' => [] },
{ '103' => [] },
{ '104' => [] },
{ '105' => [] },
{ '106' => [] },
{ '107' => [] }
] },
{ '996' => [] },
{ '997' => [ '986', '987', '990', '984', '989', '988' ] },
{ '998' => [ '908', '906', '0', '998', '907' ] },
{ '991' => [ '913', '920', '918', '998', '916', '919', '917', '915', '912', '914' ] }
]};

最佳答案

我认为这比其他任何人都更接近:

这可以满足您的大部分需求。我没有将东西存储在单数数组中
散列,因为我觉得这没什么用。

您的场景不是常规场景。我试图在某种程度上概括这一点,
但无法克服此代码的奇异性。

  • 首先,因为看起来你想用相同的方式折叠所有东西
    id 合并为一个实体(有异常(exception)),你必须通过结构下降
    拉取实体的定义。跟踪水平,因为你
    希望它们以树的形式出现。
  • 接下来,您组装 ID 表,尽可能合并实体。请注意,您
    将 995 定义为一个空数组,另一个定义为一个级别。所以给出
    您的输出,我想用散列覆盖空列表。
  • 之后,我们需要将根移动到结果结构,按顺序降序
    将规范实体分配给每个级别的标识符。

  • 就像我说的,这不是什么常规的事情。当然,如果你还想要一个列表
    不超过对的哈希值,这是留给您的练习。
    use strict;
    use warnings;

    # subroutine to identify all elements
    sub descend_identify {
    my ( $level, $hash_ref ) = @_;
    # return an expanding list that gets populated as we desecend
    return map {
    my $item = $hash_ref->{$_};
    $_ => ( $level, $item )
    , ( ref( $item ) eq 'HASH' ? descend_identify( $level + 1, $item )
    : ()
    )
    ;
    } keys %$hash_ref
    ;
    }

    # subroutine to refit all nested elements
    sub descend_restore {
    my ( $hash, $ident_hash ) = @_;

    my @keys = keys %$hash;
    @$hash{ @keys } = @$ident_hash{ @keys };
    foreach my $h ( grep { ref() eq 'HASH' } values %$hash ) {
    descend_restore( $h, $ident_hash );
    }
    return;
    }

    # merge hashes, descending down the hash structures.
    sub merge_hashes {
    my ( $dest_hash, $src_hash ) = @_;
    foreach my $key ( keys %$src_hash ) {
    if ( exists $dest_hash->{$key} ) {
    my $ref = $dest_hash->{$key};
    my $typ = ref( $ref );
    if ( $typ eq 'HASH' ) {
    merge_hashes( $ref, $src_hash->{$key} );
    }
    else {
    push @$ref, $src_hash->{$key};
    }
    }
    else {
    $dest_hash->{$key} = $src_hash->{$key};
    }
    }
    return;
    }

    my ( %levels, %ident_map, %result );

    #descend through every level of hash in the list
    # @hash_list is assumed to be whatever you Dumper-ed.
    my @pairs = map { descend_identify( 0, $_ ); } @hash_list;

    while ( @pairs ) {
    my ( $key, $level, $ref ) = splice( @pairs, 0, 3 );
    $levels{$key} |= $level;

    # if we already have an identity for this key, merge the two
    if ( exists $ident_map{$key} ) {
    my $oref = $ident_map{$key};
    my $otyp = ref( $oref );
    if ( $otyp ne ref( $ref )) {
    # empty arrays can be overwritten by hashrefs -- per 995
    if ( $otyp eq 'ARRAY' && @$oref == 0 && ref( $ref ) eq 'HASH' ) {
    $ident_map{$key} = $ref;
    }
    else {
    die "Uncertain merge for '$key'!";
    }
    }
    elsif ( $otyp eq 'HASH' ) {
    merge_hashes( $oref, $ref );
    }
    else {
    @$oref = sort { $a <=> $b || $a cmp $b } keys %{{ @$ref, @$oref }};
    }
    }
    else {
    $ident_map{$key} = $ref;
    }
    }

    # Copy only the keys that do not appear at higher levels to the
    # result hash
    if ( my @keys = grep { !$levels{$_} } keys %ident_map ) {
    @result{ @keys } = @ident_map{ @keys } if @keys;

    }
    # then step through the hash to make sure that the entries at
    # all levels are equal to the identity
    descend_restore( \%result, \%ident_map );

    关于perl - 如何在 Perl 中将多个哈希合并为一个哈希?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2767477/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com