Arrays 我应该选择散列、对象还是数组来表示Perl中的数据实例?
我一直在想这个问题,但从来没有真正彻底地研究过 情况是这样的:我有一组相对较大的数据实例。每个实例具有相同的集合或属性,例如:Arrays 我应该选择散列、对象还是数组来表示Perl中的数据实例?,arrays,perl,data-structures,hash,object,Arrays,Perl,Data Structures,Hash,Object,我一直在想这个问题,但从来没有真正彻底地研究过 情况是这样的:我有一组相对较大的数据实例。每个实例具有相同的集合或属性,例如: # a child instance name age height weight hair_color favorite_color list_of_hobbies 通常我会将一个子代表示为散列,并将所有子代放在一个散列(或一个散列数组)中 这种方法一直困扰着我的是,我没有真正使用所有子级(内部哈希)都具有相同结构的事实。如果数据真的很大,看起来可能会浪费内存,因此
# a child instance
name
age
height
weight
hair_color
favorite_color
list_of_hobbies
通常我会将一个子代表示为散列,并将所有子代放在一个散列(或一个散列数组)中
这种方法一直困扰着我的是,我没有真正使用所有子级(内部哈希)都具有相同结构的事实。如果数据真的很大,看起来可能会浪费内存,因此如果每个内部散列都是从头开始存储的,键名的名称似乎比数据本身占用的内存多得多。。。
还要注意的是,当我构建这样的数据结构时,我经常将它们存储到磁盘上
我想知道从这个角度来看,创建一个child对象是否更有意义,即使我真的不需要OO。它会更紧凑吗?查询会更快吗
或者,将每个子级表示为一个数组是有意义的?e、 g:
my ($name, $age, $height, $weight, $hair_color, $favorite_color, $list_of_hobbies) = 0..7;
my $children_h = {
James => ["James", 12, 1.62, 73, "dark brown", "blue", ["playing football", "eating ice-cream"]],
Norah => [...],
Billy => [...]
};
print "James height is $children_h->{James}[$height]\n";
回想一下,我主要关心的是空间效率(存储时为RAM或磁盘)、时间效率(即加载存储的数据集,然后从实例y获取属性x的值)和。。。方便性(代码可读性等)
谢谢 我想这主要是个人喜好(当然,当其他人也必须处理你的代码时除外) 无论如何,我认为你应该研究一下,这绝对不是最节省时间和空间的方式,但它是最愉快和最安全的工作方式。 (所谓安全,我的意思是其他使用您的对象的人不能轻易滥用它) 我个人更喜欢一个对象,当我真的代表了一些东西。 当我在perl中处理对象时,我更喜欢 Gr, ldx
每当我试图决定使用散列还是数组来存储数据时,我几乎总是使用散列。我几乎总能找到一种有用的方法来索引列表中的值,以便快速查找。但是,您的问题更多的是关于数组引用的哈希、哈希引用的哈希和对象引用的哈希 在上面的示例中,我会使用散列引用的散列,而不是数组引用的散列。我唯一会使用数组的时候是当数据中有一个应该维护的固有顺序时,这样我就可以按顺序查找。在这种情况下,您存储的数组中实际上没有任何固有的顺序(例如,您任意选择了重量之前的高度),因此更适合(以我的拙见)将数据存储为散列,其中键是您存储的数据的描述(名称、高度、重量等) 至于您应该使用散列引用还是对象引用的散列,这通常是一个偏好问题。面向对象的Perl有一些开销,所以我只在可以从可用性方面获得很大好处时才尝试使用它。我通常只在存在与数据固有关联的操作时使用对象/类(因此我可以编写
$my_obj->fix();
而不是fix($my_obj);
)。如果你只是在存储数据,我会说坚持使用散列
RAM使用率或磁盘读/写时间不应有显著差异。就可读性而言,我认为使用散列而不是数组将获得巨大的好处,因为使用散列键实际上是有意义的,但是数组只是由与数据没有实际关系的数字索引。如果以纯文本存储,这可能需要更多的磁盘空间来存储,但是如果这是一个巨大的问题,您可以随时压缩数据 我通常从一个散列开始操作它,直到找到我真正想要的数据来自我拥有的数据的实例。和/或我想要某种特殊的,甚至是多态的行为 此时,我开始创建一个包来存储类行为,并根据需要实现方法
另一种情况是,我认为这些数据在不止一种情况下是有用的。在这种情况下,要么在您认为需要的地方重写所有选择案例,要么将行为打包到一个类中,这样您就不必在下次使用该数据时对案例进行过多的复制或研究。通常,如果您不需要完全的效率,哈希将是最佳选择。在Perl中,对象只是一个附加了类名的
$something
。对象可以是散列、数组、标量、代码引用,甚至内部的glob引用。因此,对象只可能是便利的赢家,而不是效率的赢家
如果您想给一个数组一个快照,使其具有一定的可维护性的典型方法是对字段名使用常量:
use strict;
use warnings;
use constant {
NAME => 0,
AGE => 1,
HEIGHT => 2,
WEIGHT => 3,
HAIR_COLOR => 4,
FAVORITE_COLOR => 5,
LIST_OF_HOBBIES => 6,
};
my $struct = ["James", 12, 1.62, 73, "dark brown", "blue", ["playing football", "eating ice-cream"]];
# And then access it with the constants as index:
print $struct->[NAME], "\n";
$struct->[AGE]++; # happy birthday!
或者,您可以尝试使用以下数组(对象)是否更有意义:
package MyStruct;
use strict;
use warnings;
use Class::XSAccessor::Array
accessors => {
name => 0,
age => 1,
height => 2,
weight => 3,
hair_color => 4,
favorite_color => 5,
list_of_hobbies => 6,
};
sub new {
my $class = shift;
return bless([@_] => $class);
}
package main;
my $s = MyStruct->new;
$s->name("James");
$s->age(12);
$s->height(1.62);
$s->weight(73);
# ... you get the drill, but take care: The following is fine:
$s->list_of_hobbies(["foo", "bar"]);
# This can produce action-at-a-distance:
my $hobbies = ["foo", "bar"];
$s->list_of_hobbies($hobbies);
$hobbies->[1] = "baz"; # $s changed, too (due to reference)
回到我的原始观点:通常,您需要哈希或基于哈希的对象。除非需要绝对速度调整,否则我会使用Moose制作对象。对于纯速度,请使用常量索引和数组 我喜欢对象,因为它们减少了处理大深度对象所需的脑力劳动
my @all_hobbies = uniq map $_->all_hobbies,
map $_->all_students, $school->all_classrooms;
package Child;
use Moose;
has [ 'name', 'hair_color', 'fav_color' ] => (
is => 'ro',
isa => 'Str',
required => 1,
);
has [ 'age', 'height', 'weight' ] => (
is => 'ro',
isa => 'Num',
required => 1,
);
has hobbies => (
is => 'ro',
isa => 'Int',
default => sub {[]},
traits => ['Array'],
handles => {
has_no_hobbies => 'is_empty',
num_hobbies => 'count',
has_hobbies => 'count',
add_hobby => 'push',
clear_hobbies => 'clear',
all_hobbies => 'elements',
},
);
# Good to do these, see moose best practices manual.
__PACKAGE__->meta->make_immutable;
no Moose;
use List::MoreUtils qw( zip );
# Bit of messing about to make array based child data into objects;
@attributes = qw( name age height weight hair_color fav_color hobbies );
my @children = map Child->new( %$_ ),
map { zip @attributes, @$_ },
["James", 12, 1.62, 73, "dark brown", "blue", ["playing football", "eating ice-cream"]],
["Norah", 13, 1.75, 81, "black", "red", ["computer programming"]],
["Billy", 11, 1.31, 63, "red", "green", ["reading", "drawing"]],
;
# Now index by name:
my %children_by_name = map { $_->name, $_ } @children;
# Here we get kids with hobbies and print them.
for my $c ( grep $_->has_hobbies, @children ) {
my $n = $c->name;
my $h = join ", ", $c->all_hobbies;
print "$n likes $h\n";
}