Вы правы, ваше текущее решение может быть обобщено.Первая проблема состоит в том, чтобы определить жестко запрограммированные фрагменты вашей программы, которые, возможно, потребуются для различных проектов в будущем.
Только вы точно знаете, что хотите обобщить, но хэш опций FM предлагает вамочень хорошее предположение.Позвольте мне сосредоточиться на двух из этих опций,
key_cols => [0,1,2],
agg_cols => [5,6],
, где я изменил keep_cols
на key_cols
, так как мы собираемся использовать их в качестве ключей в нашем хеше данных.
Думайте о своих текущих выражениях
# version 1, key cols and agg cols hardcoded
$data->{$cols[0]}->{$cols[1]}->{$cols[2]}->[0] += $cols[5];
$data->{$cols[0]}->{$cols[1]}->{$cols[2]}->[1] += $cols[6];
как о циклах над массивами, на которые ссылаются эти два параметра.Цикл по agg_cols
является простой частью:
# version 2, generic agg cols, but key cols still hardcoded
my @agg_cols = @$opt{agg_cols};
for my $i (0..$#agg_cols}) {
$data->{$cols[0]}->{$cols[1]}->{$cols[2]}->[$i] += $cols[$agg_col[$i]];
}
Теперь, чтобы перейти к key_cols
, просто сделайте временную копию вашей ссылки на $ data и более глубоко индексируйте ее при каждом проходе:
# version 3, generic agg cols and key cols
my @agg_cols = @$opt{agg_cols};
my @key_cols = @$opt{key_cols};
my $current_ref = $data;
for my $key_col (@key_cols) {
$current_ref = $current_ref->{$cols[$key_col]};
}
for my $i (0..$#agg_cols}) {
$current_ref->[$i] += $cols[$agg_col[$i]];
}
Этот код принадлежит вашему циклу while <$in>
, за исключением того, что вы захотите провести рефакторинг, прочитав параметры agg_cols
и key_cols
только один раз в верхней части.