【问题标题】:Best way to randomly access and modify sequential data in Perl在 Perl 中随机访问和修改顺序数据的最佳方法
【发布时间】:2021-08-07 23:30:49
【问题描述】:

我的 Perl 程序的输入是一个文本文件,每行包含一个“项目”。例如,具有以下内容的文件:

  • item1 abc yyy any blabla 不管什么
  • item2 efg dod 不管 blabla mmm
  • item3 hij naa 任何东西 gagaga 不管 gooo 1,2,3
  • item4 fff ahh 不管什么 blabla 什么
  • item5 noo kir 不管什么 bbbbbb hhhhhh
  • item6 123 kkk 随便 blabla 随便
  • item7 555 yyy 任何东西 ghghgh a,b,c
  • item8 777 yxy 随便 blabla 随便

这个输入文件被读入一个数组(实际上是读入一个哈希数组,但对于这个例子,我们假设一个数组字符串):

my @items;

与每个项目相关联的是网络上的一个文件。对于输入文件中的每一项,程序都会在网络中搜索其关联文件:

my $associated_files_handle;

open ( $associated_files_filehandle, "> $associated_files_filename");

my $associated_file;

my @items_whose_associated_file_was_found;
my @items_whose_associated_file_was_not_found;

foreach my $item (@items) {
    # sub search_associated_file returns:
    #   - If associated file is  found: path to the associated file, or
    #   - If associated file not found: undef
    $associated_file = search_associated_file( $item );
    
    if (defined $associated_file) {
       print $associated_files_filehandle, "$associated_file\n";
       push @items_whose_associated_file_was_found, $item;
    } else {
       print $associated_files_filehandle, "\n";
       push @items_whose_associated_file_was_not_found, $item;
    }
}

假设找到了项目 1、2、3、6 和 8 的关联文件。上述循环完成后,输出文件将包含:

程序现在调用一个外部进程来生成项目 4、5 和 7 的关联文件:

my @missing_associated_files = generate_associated_files_of (\@items_whose_associated_file_was_not_found);

现在我有了所有项目的关联文件,并想更新输出文件以包含:

我的问题是最好的方法是什么?

一种方法是丢弃输出文件并重新运行我的程序(因为我在第一次运行结束时生成了丢失的关联文件,我知道所有关联文件都将在新运行中找到),但这是由于运行时间长,非常不受欢迎。

我正在寻找一种方法来跟踪丢失文件的索引,以便在它们生成后将它们插入到正确的位置。

我的软件技能仅限于我大约 40 年前在 Programming 101 中学到的知识,因此我非常感谢 Perl 代码形式的答案,尽管我的 S/W 素养有限,但我可以将其集成到我的程序中。

提前谢谢你。

【问题讨论】:

  • 特德您在我编辑它以使其符合您的要求和最小可重复示例时关闭了问题。
  • 这个问题还是很模糊的。您似乎正在生成某种列表,但不清楚如何生成。您询问“现有的已编译库文件的不完整列表”,但我们并不真正知道您的代码中有什么。那是数组@cells_missing_compiled_lib吗?你的问题是如何比较两个数组?
  • “程序然后调用编译器在本地生成它们。” 您的示例代码没有显示在哪里以及如何完成。请澄清。
  • TLP,我更新了我的问题以包含一个说明性示例。也许现在更清楚了。
  • Håkon,你问这是在哪里完成的?就在我的问题中的“foreach”循环完成之后。这是怎么做到的?为什么它与我的问题有关?

标签: database perl random-access


【解决方案1】:

这是一个示例,说明如何在开始写入输出文件之前提前构建文件列表:

use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures);

{
    my @items = map { "item_" . $_ } 1..10;
    my @files; # all files
    my @items_not_found; # items whose associated file was not found
    my @idx_not_found; # indexes of items not found
    for my $i (0..$#items) {
        my $item = $items[$i];
        my $associated_file = search_associated_file( $item );
        if (defined $associated_file) {
            $files[$i] = $associated_file;
        } else {
            push @items_not_found, $item;
            push @idx_not_found, $i;
        }
    }

    # The program now invokes an external process to generate the associated files
    #   for the missing items:
    @files[@idx_not_found] = generate_associated_files_of ( \@items_not_found);

    my $fn = 'associated_files.txt';
    open ( my $fh, '>', $fn ) or die "Could not open file '$fn': $!";
    for my $file (@files) {
        say $fh "$file";
    }
    close $fh;
}

sub generate_associated_files_of($items) {
    my @files;
    for my $item (@$items) {
        my ( $idx ) = $item =~ /item_(\d+)/;
        die "Unexpected index" if !defined $idx;
        push @files, "file_$idx";
    }
    return @files;
}

sub search_associated_file($item) {
    my ( $idx ) = $item =~ /item_(\d+)/;
    my %not_ok_idx = map { $_ => 1} 4,5,7;
    return undef if $not_ok_idx{$idx};
    return "file_" . $idx;
}

【讨论】:

  • 感谢 Håkon 的回答。它主要回答了我关于如何跟踪缺少关联文件的项目的索引并在生成它们后将它们插入到数组文件中间的问题。但是,我怀疑 "map { "item_" . $_ } 1..10;"依赖于每个项目以字符串 'item_' 开头,如示例中所示,但实际上它们既不以 'item_' 开头,也不按顺序编号。我过度简化了这个例子只是为了澄清我的问题,但实际上这些项目有一个复杂的结构,在内存中变成了一个哈希,所以我程序中的数组“项目”实际上是一个哈希数组。
  • 不客气! "我怀疑它依赖于每个项目以字符串 'item_'" 开头:事实上,据我所知,它并不依赖于它。只有两个 sub 依赖于它,但是这些 sub 可以根据需要进行修改。我只是把它们放在那里作为一个例子。
  • 哈康。由于您花时间编写代码,请您修改它以不依赖 'item_' 并使用 \@items 作为哈希数组。
  • "不依赖于 'item_'" :正如我上面所说,代码不依赖于字符串 item_n。无论如何,这是一个使用哈希数组的示例:pastebin.com/1tBuF93N
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多