【问题标题】:Why ever use an array instead of a hash?为什么要使用数组而不是哈希?
【发布时间】:2014-07-03 15:44:53
【问题描述】:

我已经读过,遍历哈希比遍历数组要快得多。从哈希中检索值也快得多。

为什么不使用数组,而不是使用散列并为每个键赋予一个与索引对应的值?如果需要整理物品,可以对其进行排序。

【问题讨论】:

  • 如果它们需要按照插入的顺序怎么办?
  • @RobEarl .. 你的修辞评论实际上是一个答案 - 如果它有更多细节,我会投票赞成 :)
  • 你自己试过benchmarking吗?如果你这样做了,你会发现遍历数组实际上比遍历哈希要快得多。

标签: arrays perl hash


【解决方案1】:

从某种意义上说,从哈希中检索更快,因为您可以直接通过键获取值,而不是遍历整个哈希(或在搜索特定字符串时的数组)。话虽如此,$hash{key} 并不比$array[0] 快,因为没有发生迭代。

数组不能用哈希代替,因为它们有不同的特性,

                       arrays hashes
------------------------------------
ordered keys            x       -
push/pop                x       -
suitable for looping    x       -
named keys              -       x

【讨论】:

  • 我没有想到 push/pop
  • 不知道“适合循环播放”是什么意思。您可以像遍历数组元素一样简单地遍历哈希的元素。
  • $hash{key}$array[0] 慢,但它们的缩放比例相同。
  • for @rfor 0..$#r 不会生成列表,这与 keys %h 不同,each 需要哈希重置。
【解决方案2】:

我不知道你在哪里读到哈希比数组快。根据一些 Perl 参考作品 (Mastering Algorithms with Perl),数组比散列更快(更多信息请关注 this link)。

如果速度是您的唯一标准,您应该进行基准测试,看看哪种技术会更快。这取决于您将对数组/哈希执行什么操作。

这是一个包含更多信息的 SO 链接:Advantage of 'one dimensional' hash over array in Perl

【讨论】:

    【解决方案3】:

    我认为这是一个很好的问题:它与其说是一个高级“语言设计”查询,不如说它是一个实现问题。它可以用一种强调这一点的方式措辞——比如针对特定技术或用例使用哈希与数组。

    哈希很好,但你需要列表/数组(c.f. @RobEarl)。您可以使用 tie(或 Tie::IxHashTie::Hash::Indexed 之类的模块)来“保留”哈希的顺序,但我相信这些必须比常规哈希慢,并且在某些情况下,您不能以完全相同的方式传递或复制它们。

    【讨论】:

      【解决方案4】:

      这段代码或多或少是哈希的工作方式。它应该很好地解释了为什么要使用数组而不是哈希。

      package DIYHash;
      use Digest::MD5;
      
      sub new {
           my ($class, $buckets) = @_;
      
           my $self = bless [], $class;
           $#$self = $buckets || 32;
      
           return $self;
      }
      
      sub fetch {
          my ( $self, $key ) = @_;
      
          my $i  = $self->_get_bucket_index( $key );
          my $bo = $self->_find_key_in_bucket($key);
      
          return $self->[$i][$bo][1];
      }
      
      sub store {
          my ( $self, $key, $value ) = @_;
      
          my $i  = $self->_get_bucket_index( $key );
          my $bo = $self->_find_key_in_bucket($key);
          $self->[$i][$bo] = [$key, $value];
      
          return $value;
      }
      
      sub _find_key_in_bucket {
          my ($self, $key, $index) = @_;
      
          my $bucket = $self->[$index];
      
          my $i = undef; 
          for ( 0..$#$bucket ) {
               next unless $bucket->[$_][0] eq $key;
               $i = $_;
          }
          $i = @$bucket unless defined $i;
      
          return $i;
      }
      
      
      # This function needs to always return the same index for a given key.
      # It can do anything as long as it always does that.
      # I use the md5 hashing algorithm here.
      sub _get_bucket_index {
          my ( $self, $key ) = @_;
      
          # Get a number from 0 to 1 - bucket count.
          my $index = unpack( "I", md5($key) ) % @$self;
      
          return $index;
      }
      
      1;
      

      要使用这组惊人的代码:

      my $hash = DIYHash->new(4);  #This hash has 4 buckets.
      $hash->store(mouse => "I like cheese");
      $hash->store(cat => "I like mouse");
      
      say $hash->fetch('mouse');
      

      散列看起来是常数时间,而不是 N 阶,因为对于给定的数据集,您选择的存储桶数量可以使任何存储桶中的项目数量保持非常小。

      当冲突数量过高时,适当的散列系统将能够适当地调整大小。您不想经常这样做,因为这是一个 N 阶操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-05
        • 2020-11-17
        • 2017-12-26
        • 2014-08-09
        • 2019-12-03
        • 2011-04-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多