Perl - чтение отсортированных элементов массива в хеш с отсортированными ключами - PullRequest
3 голосов
/ 11 сентября 2011

поэтому у меня есть массив (скажем, @array) с отсортированными значениями от 0 до 1, а также и хэш (скажем,% hash), ключи которого отсортированы и являются числами от 0 до 1. значения для каждого ключа вhash равен 0. Теперь мне нужно просмотреть каждый элемент @array, найти ключ в% hash, который сразу меньше его, и увеличить соответствующее значение на 1.то есть ключи служат нижними границами для интервалов

, если, скажем,

$array = (0.15,0.33,0.67,0.87) 
and %hash = ("0.25", 0, "0.50", 0, "0.75", 0)

, и я беру $array[1] = 0.33

, тогда я должен быть в состоянии определить, что$ array [1] больше, чем 0,25, НО меньше, чем 0,5, и, таким образом, увеличьте значение для «0,25» на 1, что даст мне обновленный хэш% hash = («0,25», 1, «0,50», 0, «0,75», 0).

Надеюсь, это имело смысл!заранее спасибо !!!

Ответы [ 4 ]

4 голосов
/ 11 сентября 2011

Вы строите частотное распределение для интервалов или диапазонов. У CPAN есть модули, которые это сделают. Если вы сможете переформулировать свою проблему, чтобы согласиться с тем, как эти модули понимают распределение частот, вы сможете сэкономить немного хлопот и получить доступ к другим статистическим инструментам, которые могут быть полезны для вашего проекта. Пример:

use Statistics::Descriptive;
my @data = (0.15, 0.33, 0.67, 0.87);
my @bins = (0.25, 0.50, 0.75, 1.00);
my $stat = Statistics::Descriptive::Full->new();
$stat->add_data(@data);
my $freq = $stat->frequency_distribution_ref(\@bins);

Распределение в $freq будет ссылкой на хеш-код:

$freq = {
  '0.25' => 1
  '0.5'  => 1,  # N of items x, such that PREVIOUS_BIN_VAL < x <= .50
  '0.75' => 1,
  '1'    => 1,
};

Если вы не можете изменить свою проблему, вам нужно будет самостоятельно рассчитать дистрибутив, но вы можете взять важный пример из Статистика :: Описательный . В частности, вам будет полезно иметь упорядоченный список значений бина. Вот иллюстрация:

my @data = (0.15, 0.33, 0.67, 0.87);
my @bins = (0.25, 0.50, 0.75);    # Include 0.0 if you want 0.15 to be tallied.
my %freq = map {$_ => 0} @bins;

for my $d (@data){
    for my $b (reverse @bins){
        do { $freq{$b} ++; last } if $d >= $b;
    }
}
4 голосов
/ 11 сентября 2011

Хэш не хранит ключи в отсортированном порядке. Вы должны переосмыслить свой подход к проблеме.

0 голосов
/ 11 сентября 2011

Если ваши хеш-ключи расположены равномерно, как в вашем примере, каждый из них может быть рассчитан по простой формуле, такой как $biggestSmaller = int(i*4)/4.Если нет, вам нужен вспомогательный индекс, такой как @keys = sort keys %hash - он также может быть двоичным деревом, но это достаточно тривиально, так что следует сделать простой список (а если скорость не важна, вы можете даже лениться, чтобы искатьснизу вверх, вместо реализации бинарного поиска).

0 голосов
/ 11 сентября 2011

Насколько я понял, вы хотите отслеживать, сколько элементов в $array меньше, чем ключ в %hash

Таким образом, для каждого значения ключа в хэше вы можете просто извлечь все элементы из массива, которые меньше ключа в списке, и получить его счет. Вы можете использовать grep для этого

use strict;
use warnings;
use Data::Dumper;    

my $array = [qw (0.15 0.33 0.67 0.87 1.5) ] ;
my %hash = (0.25 => 0, 0.50 => 0, 0.75 => 0, 0.05 => 0);    

for my $k (keys %hash) {
        my @filtered =  grep { $_ < $k } @$array;
        $hash{$k} = @filtered;
        #$hash{$k} = @filtered ? 1 : 0 # if you just want a flag 
}

print Dumper(\%hash);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...