【问题标题】:merging many rows into one row using a common field使用公共字段将多行合并为一行
【发布时间】:2023-03-19 17:58:01
【问题描述】:

我有一个像下面这样的文件。

1111|p1
1111|p2
1111|p3
1111|p4
1111|p5
1111|p6
2222|p1
2222|p2

等等..

一个人 (1111) 每行可以有一个产品。

我需要像下面这样的输出

1111|row1|p1|p2|p3|p4|p5
1111|row2|p6
2222|p1|p2 
3333|p1|p2|p3 

所以一行只允许最多 p5,其余的应该在第 2 行。 请帮助我在 Perl 中以这种方式获得输出。

【问题讨论】:

  • 如果“1111|p7”出现在一些 2222s 之后怎么办?它是否与其他合并?如果是,是否可以对输出进行排序,或者是否应该按照产品在文件中首次出现的顺序?
  • “row1”和“row2”真的是你想要的吗?
  • row1 和 row2 可以是任何东西,它只是为了计算每个人的行数。并且所有的数字都是排序好的,所以后面不会出现1111。

标签: perl array-merge


【解决方案1】:

使用数组的散列来存储每个人的产品:

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

my %owns;
while (<DATA>) {
    chomp;
    my ($person, $product) = split /\|/;
    push @{ $owns{$person} }, $product;
}

for my $person (keys %owns) {
    my @products = @{ $owns{$person} };
    if (@products > 5) {
        my $row = 1;
        while (@products) {
            my @five = splice @products, 0, 5;
            print join '|', $person, "row$row", @five;
            print "\n";
            $row++;
        }
    } else {
        print join '|', $person, @products;
        print "\n";
    }
}


__DATA__
1111|p1
1111|p2
1111|p3
1111|p4
1111|p5
1111|p6
2222|p1
2222|p2

【讨论】:

  • 或惯用的for (my $row = 1; @products; ++$row) {
  • @ysth, while-solutions 对我来说似乎更有机,意图如此明确。
【解决方案2】:

没有什么比程序员变得聪明更糟糕的了。

但是,下面使用正则表达式来做同样的过滤:

use strict;
use warnings;

my $data = do {local $/; <DATA>};

$data =~ s{^((\d+)\|.*\n(?:\2\|.*\n)+)}{
    my ($whole, $header) = ($1, $2);
    my @nums = map {/\|(.*)/} split "\n", $whole;
    my $return = '';
    if (@nums > 5) {
        for (my $i = 1; @nums; $i++) {
            $return .= join('|', $header, "row$i", splice @nums, 0, 5) . "\n";
        }
    } else {
        $return = join('|', $header, @nums) . "\n";
    }
    $return;
}emg;

print $data;

__DATA__
1111|p1
1111|p2
1111|p3
1111|p4
1111|p5
1111|p6
2222|p1
2222|p2

输出:

1111|row1|p1|p2|p3|p4|p5
1111|row2|p6
2222|p1|p2

【讨论】:

    猜你喜欢
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    • 2019-11-29
    • 2015-03-29
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    相关资源
    最近更新 更多