【问题标题】:merge multiple CSV files perlperl 合并多个 CSV 文件
【发布时间】:2012-11-16 08:32:53
【问题描述】:

如何在 perl 中合并多个 CSV 文件?

例如,我有文件 1 Packet1.csv 看起来像:

#type, number, info, availability
computer, t.100, pentium 2, yes
computer, t.1000, pentium 3, yes
computer, t.2000, pentium 4, no
computer, t.3000, pentium 5, yes

和文件 2 Packet2.csv 看起来像:

#type, number, info, availability
computer, t.100, pentium 2, yes
computer, t.1000, pentium 3, no
computer, t.2000, pentium 4, no
computer, t.4000, pentium 6, no

我想要的输出是单个文件,其中 数据包 的数量不固定:

#type, number, info, **Packet1** availability, **Packet2** availability
computer, t.100, pentium 2, yes, yes
computer, t.1000, pentium 3, yes, no
computer, t.2000, pentium 4, no, no
computer, t.3000, pentium 5, yes
computer, t.4000, pentium 6, no

【问题讨论】:

  • 你有多少数据?将所有内容加载到内存中是否可行?您的输入是否总是按照示例中的方式排序?
  • @Tim N 我尝试过使用多维散列
  • @TheBlackCorsair 为什么不起作用?
  • 另请参阅 stackoverflow.com/questions/13588129/…,他似乎正在与您在同一个项目上工作......
  • @pmakholm 是的,输入通常以这种方式排序有时可能包含更多项目。前三列(类型、编号、信息)是固定的,只是可用性正在发生变化。目前我有 18 个这样的 数据包,但将来可能会有所不同

标签: perl csv merge


【解决方案1】:

回到您对多维散列的尝试:Hash of hashes perl,您将需要更改您正在使用的数据结构,以便存储特定元素的多个条目。

CSV 可以直观地读入具有 2 个级别的散列。 csv 的行可以通过它们的 ID 进行散列(在这种情况下,我猜 ID 是数字 't.100'、't.1000' 等),并且每行的值可以使用存储在二级散列中标题字符串作为其键。如果您使用 Data::Dumper 查看结构,它会看起来像这样:

$VAR1 = {
          't.1000' => {
                        'info' => 'pentium 3',
                        'availability' => 'yes',
                        'type' => 'computer'
                      },
          't.100' => {
                       'info' => 'pentium 2',
                       'availability' => 'yes',
                       'type' => 'computer'
                     }
        };

“数字”是否也是每个“行哈希”的键取决于您可能有多大用处(通常您已经知道该行的键以便访问它)。

这种数据结构可以很好地存储一个 CSV 文件。但是,我们需要增加一层额外的复杂性,以便以您描述的方式合并多个 CSV。例如,为了跟踪特定 ID 出现的文件,我们可以将第三个哈希存储为“可用性”键的值,因为该值在相同“数字”的条目之间发生变化:

'availability' => {
          'Packet1' => 'yes',
          'Packet2' => 'no'
        };

一旦所有文件都被读入此结构,打印出最终的 CSV 文件就是一个循环外部哈希键的过程,并且对于每一行,以正确的顺序“连接”行的键。 'Packet' 哈希也可以循环检索所有 'availability' 值,这些值可以附加到每一行的末尾。

我希望这可以帮助您了解处理此类数据的一种可能方式。如果您发现实施的具体部分有困难,您可以询问它们,我会很乐意详细说明。

【讨论】:

  • 谢谢@kikumbob,我会试一试,我会告诉你的
【解决方案2】:
  • 如何识别哪台计算机是哪台?您是否依赖前三个字段作为计算机标识?
  • 如果第一个字段不是computer怎么办?
  • 如果这两个文件与计算机类型不一致会怎样?

您确实必须先回答这些问题,然后才能弄清楚如何处理这个问题。但是,您可能不得不处理references

我认为您的问题与标准 Perl 数据结构仅存储单个值这一事实有关。您可以拥有单个值的散列,也可以拥有单个值的数组,但每个结构中不能有多个值。 Perl 通过使用 references 解决了这个问题。

例如,假设您有一个名为 %computer 的哈希,它由第二个字段作为键:

my %system;

$system{t.100} = {}    #This is a hash of hashes
$system{t.100}->{INFO} = "pentium 2";
$system{t.100}->{TYPE} = "computer";
$computer{t.100}->{AVAILABLITY} = []  #Storing an array in this hash entry (hash of hashes of arrays)
$computer{t.100}->{AVAILABILITY}->[0] = "yes";
$computer{5.100}->{AVAILABILITY}->[1] = "yes";

您还可以通过取消引用数组来使用pushpop

push @{ $computer{t.100}->{AVAILABILITY} }, "yes";

请注意,我用@{...} 包围了对数组$computer{t.100}->{AVAILABILITY} 的引用,它从对数组的引用返回到数组。

我希望这就是你要问的。您可以使用 Text::CSV 模块来解析您的 CSV 文件,但如果格式不太古怪,您可能只需使用 split 命令即可。

【讨论】:

    猜你喜欢
    • 2013-08-02
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 2019-10-11
    • 2018-06-11
    • 2021-05-17
    • 2014-01-29
    相关资源
    最近更新 更多