Perl - Сортировать га sh для трехмерного массива с GROUP по - PullRequest
0 голосов
/ 07 апреля 2020

В Perl, у меня есть многомерная ха sh месячная продажа в этой форме:

monthlysale{$year}{$qtr}{itemcode}

Пример этого:

monthlysale{2013}{3}{MNB}= is 5
monthlysale{2013}{3}{ABC}= is 24
monthlysale{2013}{3}{CL}= is 336
monthlysale{2013}{3}{XNX}= is 18
monthlysale{2013}{3}{CVG}= is 15
monthlysale{2013}{3}{CTP}= is 11
monthlysale{2013}{3}{CPE}= is 86
monthlysale{2013}{4}{MNB}= is 47
monthlysale{2013}{4}{ABC}= is 60
monthlysale{2013}{4}{CL}= is 39
monthlysale{2013}{4}{XNX}= is 16
monthlysale{2013}{4}{CVG}= is 26
monthlysale{2013}{4}{CTP}= is 19

и аналогичный для другие годы и месяцы, для списка элементов.

Однако вышеупомянутое НЕ в указанном порядке, вместо этого оно случайным образом размещается для года и квартала.

Мое требование - распечатать Выход SORTED, который должен быть отсортирован от высокой стоимости продаж к низкой стоимости продаж, но должен быть сгруппирован по году и кварталу.

Например, желаемый результат должен быть:

monthlysale{2013}{3}{CL}= is 336
monthlysale{2013}{3}{CPE}= is 86
monthlysale{2013}{3}{ABC}= is 24
monthlysale{2013}{3}{XNX}= is 18
monthlysale{2013}{3}{CVG}= is 15
monthlysale{2013}{3}{CTP}= is 11
monthlysale{2013}{3}{MNB}= is 5


monthlysale{2013}{4}{ABC}= is 60
monthlysale{2013}{4}{MNB}= is 47
monthlysale{2013}{4}{CL}= is 39
monthlysale{2013}{4}{CVG}= is 26
monthlysale{2013}{4}{CTP}= is 19
monthlysale{2013}{4}{XNX}= is 16

и и т. д.

То есть ... выходные данные должны начинаться с самого первого доступного года (первое измерение), проходить через квартальные значения 1, 2,3,4 (второе измерение) и перечислять код элемента (CL, CPE, AB C, et c. - третье измерение) и значения массива (336,86, 24 ...) в порядке убывания значений массива.

Я попробовал следующий код, но

foreach $yr (@yeararray) #This array is sorted (2001,2002,2003....)
{
    foreach $qt (@qtrarray) #This array is sorted (1,2,3,4)
    {
        foreach my $name (sort { $monthlysale{$yr}{$qt}{$a} <=> $monthlysale{$yr}{$qt}{$b} or $a cmp $b } keys %monthlysale{$yr}{$qt})
        {
            printf "%-8s %s\n", $name, $monthlysale{$yr}{$qt}{$name};
        }
    }
}

Но он возвращает ошибку: "Experimental keys on scalar is now forbidden at script.pl line 111, <DATA> line 1."

Что такое Я делаю неправильно здесь. и что можно сделать, чтобы получить желаемый результат, пожалуйста?

PS: данные в формате CSV, как это требуется в комментарии:

2013,3,MNB,5
2013,3,ABC,24
2013,3,CL,336
2013,3,XNX,18
2013,3,CVG,15
2013,3,CTP,11
2013,3,CPE,86
2013,4,MNB,47
2013,4,ABC,60
2013,4,CL,39
2013,4,XNX,16
2013,4,CVG,26
2013,4,CTP,19

1 Ответ

1 голос
/ 07 апреля 2020

Следующий фрагмент кода демонстрирует, как можно сгенерировать желаемый результат.

Код состоит из двух подпрограмм read_data и print_sorted

до ласточка данные в га sh хешей с sub read_data

выходные данные отсортированы га sh с sub print_sorted

  • сортировка га sh по годам

  • сортировка га sh по кварталам

  • генерация нового га sh, где мы меняем ключи и значения

  • сортировка нового га sh по ключам сумма

  • выходное имя га sh значение и сумма

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my $debug = 0;

my $data = read_data();

say Dumper($data) if $debug;

print_sorted($data);

sub print_sorted {
    my $data = shift;

    for my $year ( sort keys %{$data} ) {
        for my $quarter ( sort keys %{$data->{$year}} ) {
            my @amount = values %{$data->{$year}{$quarter}};
            my @items  = keys %{$data->{$year}{$quarter}};

            my %hash;
            @hash{@amount} = @items;

            for my $amount ( reverse sort {$a <=> $b} keys %hash ) {
                say "sales{$year}{$quarter}{$hash{$amount}} = $amount";
            }

            say '';
        }
    }
}


sub read_data {
    my %data;

    while( <DATA> ) {
        chomp;
        my($y,$i,$s,$a)   = split ',';
        $data{$y}{$i}{$s} = $a;
    }

    return \%data;
}

__DATA__
2013,3,MNB,5
2013,3,ABC,24
2013,3,CL,336
2013,3,XNX,18
2013,3,CVG,15
2013,3,CTP,11
2013,3,CPE,86
2013,4,MNB,47
2013,4,ABC,60
2013,4,CL,39
2013,4,XNX,16
2013,4,CVG,26
2013,4,CTP,19

Выход

sales{2013}{3}{CL} = 336
sales{2013}{3}{CPE} = 86
sales{2013}{3}{ABC} = 24
sales{2013}{3}{XNX} = 18
sales{2013}{3}{CVG} = 15
sales{2013}{3}{CTP} = 11
sales{2013}{3}{MNB} = 5

sales{2013}{4}{ABC} = 60
sales{2013}{4}{MNB} = 47
sales{2013}{4}{CL} = 39
sales{2013}{4}{CVG} = 26
sales{2013}{4}{CTP} = 19
sales{2013}{4}{XNX} = 16
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...