首页 > 解决方案 > 以特定格式重新组织哈希

问题描述

%files_data = {                                                                                                                                                                                                                                     

              './GetOpt.pm' => {
                          'pid' => {
                                     '56061' => 1,
                                     '56065' => 1
                                   }
                            },
              'file1' => {
                          'pid' => {
                                     '56061' => 2
                                   }
                        },
              'file2' => {
                         'pid' => {
                                    '56065' => 2
                                  }
                       },
              './src/bin/perl' => {
                            'pid' => {
                                       '56061' => 1,
                                       '56065' => 1
                                     }
                          }
                    };

%process_data = (

          '56061' => {
                       'parent' => 'NA',
                       'name' => 'file1'
                     },
          '56069' => {
                       'parent' => '56065',
                       'name' => 'echo Hello_file1'
                     },
          '56062' => {
                       'parent' => '56061',
                       'name' => 'echo Hello_file2'
                     },
          '56065' => {
                       'parent' => '56061',
                       'name' => 'file2'
                     }
        );

我想遍历$files_data哈希并为每个文件获取文件链。所以我会得到以下哈希:

%hash = (
        'file1' => {
            '/src/bin/perl' => 1,
            'file2' => { 
                '/src/bin/perl' => 1,
                './GetOpt.pm' => 1
            },
            './GetOpt.pm' => 1,
    }
);

我需要跟踪每个文件的主父('NA')的 pid 链。

解决它的最有效方法是什么?我需要一些关于如何实现它的指导。

编辑:让我们以'./GetOpt.pm'文件为例。它有一个pid 56061,所以我们去%process_data看看'file1'(这是一个文件)。我们还看到56061is的父级,NA所以我们停下来得到:

file1 => ./GetOpt.pm

但是./GetOpt.pm有另一个 pid -56065所以我们去56065看看file2(这是一个文件)。然后我们去56061which has file1(这是s文件)。所以我们得到:

file1 => file2 => ./GetOpt.pm

结合它:

file1 => {
    ./GetOpt.pm,
    file2 => ./GetOpt.pm
}

我想建立一个流程文件链(仅包含文件)。%files_data包含有效文件并%process_data包含我们需要遵循的流程的层次结构

标签: perl

解决方案


我使用了一个递归子程序,它将文件名链添加到现有哈希中。我必须通过./src/bin/perl.

#!/usr/bin/perl
use warnings;
use strict;

my %files_data = (
    './GetOpt.pm'    => {pid => {56061 => 1,
                                 56065 => 1}},
    'file1'          => {pid => {56061 => 2}},
    'file2'          => {pid => {56065 => 2}},
    './src/bin/perl' => {pid => {56061 => 1,
                                 56065 => 1}}
);

my %process_data = (
    '56061' => {'parent' => 'NA',
                'name' => 'file1'},
    '56069' => {'parent' => '56065',
                'name' => 'echo Hello_file1'},
    '56062' => {'parent' => '56061',
                'name' => 'echo Hello_file2'},
    '56065' => {'parent' => '56061',
                'name' => 'file2'}
);

my %expected = (
    'file1' => {
        './src/bin/perl' => 1,
        'file2' => {
            './src/bin/perl' => 1,
            './GetOpt.pm' => 1
        },
        './GetOpt.pm' => 1,
    }
);

use Test::More;
use Test::Deep;

sub hashify {
    my ($tree, @chain) = @_;
    my $head = shift @chain;
    $tree->{$head} = @chain ? {} : 1 unless ref $tree->{$head};
    hashify($tree->{$head}, @chain) if @chain;
}

sub add {
    my ($tree, $key) = @_;
    for my $pid (keys %{ $files_data{$key}{pid} }) {
        my @chain = $key;
        while ($pid ne 'NA') {
            my ($parent, $name) = @{ $process_data{$pid} }{qw{ parent name }};
            unshift @chain, $name unless $name eq $chain[0];
            $pid = $parent;
        }
        hashify($tree, @chain);
    }
}

my $result = {};
add($result, $_) for keys %files_data;

cmp_deeply($result, \%expected);
done_testing();

推荐阅读