我有一个整数值列表;这些整数值中的每一个都与实际值相关联。
给你一个想法,他们可能会这样表示:
1 0.48
5 0.56
6 0.12
20 1.65
25 1.50
并非所有整数都在列表中表示,只有具有与之关联的值的那些整数。
给定一系列整数值,我必须对与范围的极值之间的任何整数相关联的实数值执行一些操作。例如:
给定范围5-20,我需要提取与整数5,6和20相关的实数值,然后对它们执行一些操作。
现在我能想到的最好的方法是使用整数值作为哈希的键,并循环遍历所有排序的整数值,并检查每个值是否在范围之间;像这样:
foreach (sort key %hash)
{
if ($_ >= $rangemin && $_ <= $rangemax)
{
push @somearray, $hash{$_}
}
last if $_ >= $rangemax;
}
然而,我正在处理的真实列表要长得多,而且这种实现需要花费大量时间来执行。
是否有更快/更有效的方法来获取位于数组中两个任意值之间的值列表?
答案 0 :(得分:3)
不要排序,没有必要。
这可能会稍快一些:
@somearray = @hash{ grep $_ >= $rangemin && $_ <= $rangemax, keys %hash };
(通过使用grep过滤所有键来构建所需索引的列表,然后使用哈希切片一次获取所有值)。
您必须对其进行基准测试才能确定。
另一种选择是从$ rangemin循环到$ rangemax:
for ($rangemin..$rangemax) {
push @somearray, $hash{$_} if exists $hash{$_};
}
或
for ($rangemin..$rangemax) {
push @somearray, $hash{$_} // ();
}
或
@somearray = @hash{ grep exists $hash{$_}, $rangemin..$rangemax };
哪个最快将取决于数据的稀疏程度,范围的大小以及您所包含的哈希值的百分比。
答案 1 :(得分:2)
是否更快可能取决于您的数据,但您可以简单地循环数字,并检查它们是否存在:
for my $num ($rangemin .. $rangemax) {
if (defined $hash{$num}) { # number exists
# do stuff
}
}
作为对此的变体,您可以使用grep
来获取索引列表:
my @range = grep defined($hash{$_}), $rangemin .. $rangemax;
答案 2 :(得分:1)
您不需要进行完整的集合扫描,只需迭代5-20并从集合中获取与该键相关联的值(如果存在(is not undef
或defined
)