【问题标题】:Need to sort 4 different arrays based on the sorting of a separate array需要根据单独数组的排序对4个不同的数组进行排序
【发布时间】:2014-10-02 07:33:44
【问题描述】:

我希望根据从 CSV 文件中提取的数据填充几个数组。

现在在我的脚本中,我逐行读取文件并取出我需要的每一列并将其放入单独的数组中(例如,服务器主机名放入 @server 数组,容量信息放入 @容量数组等)

填充数组后,我使用简单的 for 循环将它们打印出来

for (my $i = 0; $i < @server; $i++)
{
    #print different arrays by using $i for the key
}

目前这是可行的,因为在我将所有信息存储到数组中的循环中,它是线性完成的,因此每个数组索引都匹配其他数组中的信息。

但是,我现在需要在 @server 数组中按服务器对信息进行排序。我想做的是按字母顺序对@server 数组进行排序,但是让(排序前)匹配的其他数组中的每个索引也得到相同的排序。

我一直在尝试解决这个问题,在散列和多维数组之间进行转换,此外,我对 Perl 还比较陌生,这对我来说变得非常困难。

下面是我用来从 CSV 文件中提取信息的代码。我知道 Text::CSV 模块,但是我无法安装其他模块。

while (my $line = <INFILE>)
{
    chomp($line);
    if (index($line, "ONSITE") == -1 && index($line, "IBM3584") != -1)
    my @separated = split(',', $line);
    if ($separated[4] > 0)
    {
        push (@server, $separated[0]);
        push (@slot, $separated[7]);
        push (@volume, $separated[1]);
        push (@used, $separated[8]);
        push (@pool, $separated[3]);
    }
}

【问题讨论】:

    标签: arrays perl sorting csv indexing


    【解决方案1】:

    如果你想保持你的数据结构不变,你可以按索引排序

    use strict;
    use warnings;
    
    my (@fruit, @line, @color);
    
    while (<DATA>) {
        chomp;
        my @cols = split ',';
        push @fruit, $cols[0];
        push @line, $cols[1];
        push @color, $cols[2];
    }
    
    for my $index (sort {$fruit[$a] cmp $fruit[$b]} (0..$#fruit)) {
        printf "%-12s %-8s %s\n", $fruit[$index], $line[$index], $color[$index];
    }
    
    __DATA__
    apple,line 1,red
    orange,line 2,orange
    pear,line 3,green
    strawberry,line 4,red
    banana,line 5,yellow
    kiwi,line 6,greyish green
    

    输出:

    apple        line 1   red
    banana       line 5   yellow
    kiwi         line 6   greyish green
    orange       line 2   orange
    pear         line 3   green
    strawberry   line 4   red
    

    但是,如果将您的数据组合在一起有意义,我会建议使用散列数组来代替:

    my @records;
    
    while (<DATA>) {
        chomp;
        my @cols = split ',';
        push @records, {
            fruit => $col[0],
            line  => $col[1],
            color => $col[2],
        };
    }
    
    for my $record (sort {$a->{fruit} cmp $b->{fruit}} @records) {
        printf "%-12s %-8s %s\n", @{$record}{qw(fruit line color)};
    }
    

    【讨论】:

    • +1:AoH 可能是最好的方法!哈希切片的巧妙使用(炫耀!)
    • 这似乎是一个非常干净的选项,也是我想使用的选项。我会尝试一下,如果我有任何问题或 cmets,请告诉您。谢谢!
    • 哇。这太棒了!更不用说它看起来比我试图破解的要干净得多。如果可以,你能解释一下 for 循环的第一行吗?更具体地说,它在排序中做了什么?
    • @MikeRinehart 由于您已经构造了array of hashes,它使用字符串比较运算符(cmp)对fruit 键引用的值进行排序。在for loop 之前添加use Data::Dumper;print Dumper \@records; 以查看您的数据结构。这会有所帮助。
    • @MikeRinehart 很高兴我们找到了适合您的解决方案。我可以尝试解释sort 在该行中所做的事情,但老实说,通过研究文档,您可能会获得更多信息。有一些基于哈希值排序的示例。此外,对于 AoH(哈希数组)不熟悉,我建议您查看 Data Structures Cookbook
    【解决方案2】:

    @server数组的索引进行排序,然后按照排序后的索引排列每个数组:

    my @indexes = sort { $server[$a] cmp $server[$b] } 0 .. $#servers;
    
    @servers  = @servers[@indexes];
    @capacity = @capacity[@indexes];
    # etc.
    

    但一般来说,您可能想研究将散列放入数组的想法,例如:

    @servers = (
        { name => 'foo', capacity => 'whatever', ... },
        # ...
    );
    
    @servers = sort { $a->{name} cmp $b->{name} } @servers;
    

    【讨论】:

      猜你喜欢
      • 2023-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-10
      • 1970-01-01
      • 2018-07-13
      • 2015-04-08
      相关资源
      最近更新 更多