I have an array of objects, and an array of acceptable return values for a particular method. How do I reduce the array of objects to only those whose method in question returns a value in my array of acceptable values?
我有一个对象数组,以及一个特定方法的可接受返回值数组。如何将对象数组减少到只有那些方法在我的可接受值数组中返回值的对象?
Right now, I have this:
现在,我有这个:
my @allowed = grep {
my $object = $_;
my $returned = $object->method;
grep {
my $value = $_;
$value eq $returned;
} @acceptableValues;
} @objects;
The problem is that this is a compound loop, which I'd like to avoid. This program is meant to scale to arbitrary sizes, and I want to minimize the number of iterations that are run.
问题是这是一个复合循环,我想避免。该程序旨在扩展到任意大小,我想最小化运行的迭代次数。
What's the best way to do this?
最好的方法是什么?
2 个解决方案
#1
7
You could transform the accepted return values into a hash
您可以将接受的返回值转换为哈希值
my %values = map { $_ => 1 } @acceptedValues;
And grep
with the condition that the key exists instead of your original grep:
并且grep具有密钥存在而不是原始grep的条件:
my @allowed = grep $values{ $_->method }, @objects;
Anyway, grep
is pretty fast in itself, and this is just an idea of a common approach to checking if an element is in an array. Try not to optimize what's not needed, since it would only be worth in really big arrays. Then you could for example sort the accepted results array and use a binary search, or cache results if they repeat. But again, don't worry with this kind of optimisation unless you're dealing with hundreds of thousands of items — or more.
无论如何,grep本身相当快,这只是一种检查元素是否在数组中的常用方法的想法。尽量不要优化不需要的东西,因为它只适用于非常大的数组。然后你可以例如对接受的结果数组进行排序并使用二进制搜索,或者如果它们重复则缓存结果。但是,除非你要处理数十万件物品,否则不要担心这种优化。
#2
1
Elements supposed to be present in given arrays seems unique. So, I will make a hash containing the count of elements from both arrays. If there is any element with count greater than 1, it means its present in both the arrays.
应该存在于给定数组中的元素似乎是唯一的。所以,我将创建一个包含两个数组中元素数的哈希值。如果有任何count大于1的元素,则表示它在两个数组中都存在。
my %values;
my @allowed;
map {$values{$_}++} (@acceptableValues, @objects);
for (keys %values) {
push @allowed, $_ if $values{$_} > 1;
}
#1
7
You could transform the accepted return values into a hash
您可以将接受的返回值转换为哈希值
my %values = map { $_ => 1 } @acceptedValues;
And grep
with the condition that the key exists instead of your original grep:
并且grep具有密钥存在而不是原始grep的条件:
my @allowed = grep $values{ $_->method }, @objects;
Anyway, grep
is pretty fast in itself, and this is just an idea of a common approach to checking if an element is in an array. Try not to optimize what's not needed, since it would only be worth in really big arrays. Then you could for example sort the accepted results array and use a binary search, or cache results if they repeat. But again, don't worry with this kind of optimisation unless you're dealing with hundreds of thousands of items — or more.
无论如何,grep本身相当快,这只是一种检查元素是否在数组中的常用方法的想法。尽量不要优化不需要的东西,因为它只适用于非常大的数组。然后你可以例如对接受的结果数组进行排序并使用二进制搜索,或者如果它们重复则缓存结果。但是,除非你要处理数十万件物品,否则不要担心这种优化。
#2
1
Elements supposed to be present in given arrays seems unique. So, I will make a hash containing the count of elements from both arrays. If there is any element with count greater than 1, it means its present in both the arrays.
应该存在于给定数组中的元素似乎是唯一的。所以,我将创建一个包含两个数组中元素数的哈希值。如果有任何count大于1的元素,则表示它在两个数组中都存在。
my %values;
my @allowed;
map {$values{$_}++} (@acceptableValues, @objects);
for (keys %values) {
push @allowed, $_ if $values{$_} > 1;
}