我有一個 hashref,它的資料與日歷年的天數相關,例如:
my $calendarEntries = { '1' => 'Entry 1', '5' => 'Entry 2', '15' => 'Entry 3' };
我可以使用以下方法獲得一年中的哪一天DateTime:
state $moduleDateTime = require DateTime;
my $dt = DateTime->now('time_zone' => 'America/Chicago');
my $dayOfTheYear = $dt->strftime('%j');
但是,我試圖找出最有效的方法來處理當前日期與哈希中的任何日期都不匹配的情況。在這些情況下,我想總是“四舍五入”。例如今天(這是一年中的第 7 天),我想用鍵“5”加載條目,因為它是最新的“最近”條目。
有沒有辦法在 hashref 中選擇一個最接近的候選鍵<= $dayOfTheYear?如果我使用 DBD,我可以執行如下查詢:
'SELECT entry WHERE `key` <= ' . $dayOfTheYear . ' ORDER BY `key` DESC LIMIT 1'
但是,如果我可以在 Perl 中本地做一些事情,我寧愿避免需要創建一個資料庫并呼叫它。
uj5u.com熱心網友回復:
一種方式,期待許多搜索
use List::MoreUtils qw(last_value);
my @entries = sort { $a <=> $b } keys %$calendarEntries;
my $nearest_le = last_value { $day >= $_ } @entries;
對于任何輸入,這將回傳小于或等于的最后一個元素,因此是感興趣的鍵。
簡單地使用哈希的缺點是需要額外的資料結構來構建。當然,任何提供這種查找的庫也必須這樣做,但是那些會附帶其他好東西,并且性能可能要好得多(取決于這樣做的頻率)。
如果對于給定的哈希需要做很多“舍入” ,那么構建一個查找表幾天是有意義的,將每個與哈希中最近的鍵相關聯。? ?
如果@entries按降序排序 ( $b <=> $a),那么核心List::Util::first會執行此操作。
?例如
my %nearest_le;
my @keys = sort { $a <=> $b } keys %$calendarEntries;
for my $day (1..366) {
for my $k (@keys) {
if ($k <= $day) {
$nearest_le{$day} = $k;
}
else { last }
}
};
如問題中所述,這將列舉一年中的日子。
?如果除了可能需要長串列的日子(最多 366 天)之外的其他事情需要這樣做,則對排序串列 ( O(log n) ) 進行二進制搜索可以提供更好的演算法行為。
上面使用的庫List::MoreUtils也有lower_boundO (log n)
回傳 LIST 中不小于 val的第一個元素的索引。
所以這需要一些調整,因為
use List::MoreUtils qw(lower_bound);
my @keys = sort { $a <=> $b } keys %$calendarEntries;
my $nearest_le = exists $calendarEntries->{$day}
? $day
: $keys[ -1 lower_bound { $_ <=> $day } @keys ];
uj5u.com熱心網友回復:
一個不錯的簡單解決方案。
use List::Util qw( max );
max grep { $_ <= $dayOfTheYear } keys %$calendarEntries
筆記:
- 最好先確定
$calendarEntries->{ $dayOfTheYear }不存在。 - 您需要處理沒有匹配鍵的情況。
除非您執行多次搜索,否則它比排序更快。但即便如此,我們最多只能處理 365 個鍵,所以這里的關鍵是簡單。
uj5u.com熱心網友回復:
最簡單的解決方案是簡單地查找您的日期的值,如果沒有找到,請繼續下去,直到找到一個值。在這個示例中,我包含了一個基本的錯誤處理。
use strict;
use warnings;
use feature 'say';
my $calendarEntries = { '1' => 'Entry 1', '5' => 'Entry 2', '15' => 'Entry 3' };
my $find = shift // 7; # for testing purposes
my $date = get_nearest_below($calendarEntries, $find);
if (defined $date) {
say "Nearest date below to '$find' is '$date'";
} else { # error handling
warn "Nearest date below not found for '$find'";
}
sub get_nearest_below {
my ($href, $n) = @_;
while ($n > 0) { # valid dates are > 0
return $n if defined $href->{$n}; # find a defined value
$n--; # or go to the next key below
}
return undef; # or return error if nothing is found before 0
}
輸出:
$ foo.pl
Nearest date below to '7' is '5'
$ foo.pl 12
Nearest date below to '12' is '5'
$ foo.pl 123
Nearest date below to '123' is '15'
$ foo.pl 0
Nearest date below not found for '0' at foo.pl line 13.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/410912.html
標籤:
上一篇:SQLSTATE[22007]:日期時間格式無效:1292日期時間值不正確:“fotostudio”列的“28-01-202212:00”。“transaction_details”
下一篇:在特定時間重置本地存盤變數
