Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 我应该选择散列、对象还是数组来表示Perl中的数据实例?_Arrays_Perl_Data Structures_Hash_Object - Fatal编程技术网

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足够聪明,可以在散列之间共享密钥。如果有100000个具有相同五个键的散列,perl将存储这五个字符串一次,并引用它们十万次。担心空间效率是不值得的

  • 基于散列的对象是最常见的类型,也是最容易处理的,所以除非你有很好的理由不使用它们,否则你应该使用它们

  • 您应该为自己省去很多麻烦,开始使用并停止担心对象的内部结构(不过,就在您和我之间,Moose对象是基于哈希的,除非您使用特殊的扩展来实现它们——再说一次,没有真正好的理由,您不应该这样做。)


  • 每当我试图决定使用散列还是数组来存储数据时,我几乎总是使用散列。我几乎总能找到一种有用的方法来索引列表中的值,以便快速查找。但是,您的问题更多的是关于数组引用的哈希、哈希引用的哈希和对象引用的哈希

    在上面的示例中,我会使用散列引用的散列,而不是数组引用的散列。我唯一会使用数组的时候是当数据中有一个应该维护的固有顺序时,这样我就可以按顺序查找。在这种情况下,您存储的数组中实际上没有任何固有的顺序(例如,您任意选择了重量之前的高度),因此更适合(以我的拙见)将数据存储为散列,其中键是您存储的数据的描述(名称、高度、重量等)

    至于您应该使用散列引用还是对象引用的散列,这通常是一个偏好问题。面向对象的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";
    }