perl - 在作为另一个对象访问器的对象列表中搜索
perl - searching in list of objects which are an accessor of another object
我是 Perl-OO 初学者,我遇到了设计挑战。我希望你能给我一些提示,以找到一个优雅的解决方案。我在这里使用鼠标对象系统。
举一个最小的例子,假设我有一个用户对象。一个用户有一个名字。
package User;
use Mouse;
has "name" => (
is => "rw",
isa => "Str|Undef",
);
然后我有一个用户缓存对象,它获取所有用户的列表(来自 LDAP 服务器)。你可以说这是用户缓存和用户之间的 "has-a" 关系。
package UserCache;
use Mouse;
has "users" => (
is => 'rw',
isa => 'ArrayRef|Undef',
default => sub { [] },
);
我将这个用户列表作为用户对象数组存储在用户缓存的访问器中。
my $cache = UserCache->new();
foreach my $entry ( $ldap->searchGetEntries() ) {
my $user = User->new();
$user->name($entry->get_value('userdn'));
push @{ $cache->users }, $user;
}
现在这就是我的问题所在。如果我想找到具有特定属性的用户对象(例如,名为 John 的用户),我必须遍历整个用户对象数组并查询每个对象因为它的名字。当给出一个名称列表时,这将是一个非常低效的过程。
foreach my $user ( @{ $cache->users } ) {
if ( $user->name eq 'John' ) {
#do something with John
}...
}
有没有一种方法可以将对象列表存储在其他对象中,以便我可以高效地搜索?比如 $cache->get_users->get_name('John') 和 returns 我需要的对象?
否。至少不是普遍的。您当然可以为常见的事物建立索引。或者您可以在完成搜索后缓存搜索。
查找最好以散列的形式实现。这些可以附加到 UserCache 对象。类似于:
my @users = $cache->find( name => 'John' );
这将在内部映射到带有搜索字段的哈希引用。
package UserCache;
#...
has _search_index => (
is => 'ro',
isa => 'HashRef',
default => sub { {} },
);
哈希引用看起来像这样:
{
name => {
John => [
User->new( name => 'John', last_name => 'Smith' ),
User->new( name => 'John', last_name => 'Wayne' ),
User->new( name => 'John', last_name => 'Bon Jovi' ),
],
James => [ ... ],
},
id => {
# ...
},
),
但同样,您必须构建这些。所以你需要做一次查找。但我认为查找应该在 UserCache 内部完成并存储在那里。
sub find {
my ($self, $key, $value) = @_;
# get operation
return @{ $self->_search_index->{$key}->{$value} }
if exists $self->_search_index->{$key}->{$value};
# set operation
foreach my $user ( @{ $self->users } ) {
push @{ $self->_search_index->{$key}->{$value} }, $user
if $user->$key eq $value
}
return @{ $self->_search_index->{$key}->{$value} }
}
这是一个非常幼稚的实现,它不支持多次查找,但这是一个开始。
请注意,如果您有很多用户和很多索引,数据结构可能会变大。
为了方便起见,Moose's built-in traits might be helpful. If you want a stronger cache behavior, look at CHI。
您实际上不必自己编写 UserCache
class。相反,使用 CHI 来缓存您要缓存的用户,该用户要缓存在您要用于查找的键下。如果需要,您可以包装缓存 class 以从特定的缓存实现中抽象出来。
另外,你有这个:
push @{ $cache->users }, $user;
你在哪里泄露了实现细节。相反,您的 UserCache
对象需要类似 save_user
方法的东西,因此它使用的代码不依赖于实现细节。
$cache->save_user( $user );
对于 Moose 对象,您得到 Moose::Meta::Attribute::Native::Trait::Array; for Mouse, you get MouseX::NativeTraits::ArrayRef。
我是 Perl-OO 初学者,我遇到了设计挑战。我希望你能给我一些提示,以找到一个优雅的解决方案。我在这里使用鼠标对象系统。
举一个最小的例子,假设我有一个用户对象。一个用户有一个名字。
package User;
use Mouse;
has "name" => (
is => "rw",
isa => "Str|Undef",
);
然后我有一个用户缓存对象,它获取所有用户的列表(来自 LDAP 服务器)。你可以说这是用户缓存和用户之间的 "has-a" 关系。
package UserCache;
use Mouse;
has "users" => (
is => 'rw',
isa => 'ArrayRef|Undef',
default => sub { [] },
);
我将这个用户列表作为用户对象数组存储在用户缓存的访问器中。
my $cache = UserCache->new();
foreach my $entry ( $ldap->searchGetEntries() ) {
my $user = User->new();
$user->name($entry->get_value('userdn'));
push @{ $cache->users }, $user;
}
现在这就是我的问题所在。如果我想找到具有特定属性的用户对象(例如,名为 John 的用户),我必须遍历整个用户对象数组并查询每个对象因为它的名字。当给出一个名称列表时,这将是一个非常低效的过程。
foreach my $user ( @{ $cache->users } ) {
if ( $user->name eq 'John' ) {
#do something with John
}...
}
有没有一种方法可以将对象列表存储在其他对象中,以便我可以高效地搜索?比如 $cache->get_users->get_name('John') 和 returns 我需要的对象?
否。至少不是普遍的。您当然可以为常见的事物建立索引。或者您可以在完成搜索后缓存搜索。
查找最好以散列的形式实现。这些可以附加到 UserCache 对象。类似于:
my @users = $cache->find( name => 'John' );
这将在内部映射到带有搜索字段的哈希引用。
package UserCache;
#...
has _search_index => (
is => 'ro',
isa => 'HashRef',
default => sub { {} },
);
哈希引用看起来像这样:
{
name => {
John => [
User->new( name => 'John', last_name => 'Smith' ),
User->new( name => 'John', last_name => 'Wayne' ),
User->new( name => 'John', last_name => 'Bon Jovi' ),
],
James => [ ... ],
},
id => {
# ...
},
),
但同样,您必须构建这些。所以你需要做一次查找。但我认为查找应该在 UserCache 内部完成并存储在那里。
sub find {
my ($self, $key, $value) = @_;
# get operation
return @{ $self->_search_index->{$key}->{$value} }
if exists $self->_search_index->{$key}->{$value};
# set operation
foreach my $user ( @{ $self->users } ) {
push @{ $self->_search_index->{$key}->{$value} }, $user
if $user->$key eq $value
}
return @{ $self->_search_index->{$key}->{$value} }
}
这是一个非常幼稚的实现,它不支持多次查找,但这是一个开始。
请注意,如果您有很多用户和很多索引,数据结构可能会变大。
为了方便起见,Moose's built-in traits might be helpful. If you want a stronger cache behavior, look at CHI。
您实际上不必自己编写 UserCache
class。相反,使用 CHI 来缓存您要缓存的用户,该用户要缓存在您要用于查找的键下。如果需要,您可以包装缓存 class 以从特定的缓存实现中抽象出来。
另外,你有这个:
push @{ $cache->users }, $user;
你在哪里泄露了实现细节。相反,您的 UserCache
对象需要类似 save_user
方法的东西,因此它使用的代码不依赖于实现细节。
$cache->save_user( $user );
对于 Moose 对象,您得到 Moose::Meta::Attribute::Native::Trait::Array; for Mouse, you get MouseX::NativeTraits::ArrayRef。