在Crystal,哈希或查找的案例表达式中哪个会更快?

dgo*_*o.a 1 crystal-lang

在针对已知组,Hash(String => Bool)或case?的情况下查找字符串会更快.

input = %w(a b c x y z)
valid = { "a" => true, "z" => true }
input.find { |x|

  !valid.has_key?(x)

  # or

  case x
  when "a", "z"
    false
  else
    true
  end
}
Run Code Online (Sandbox Code Playgroud)

Fau*_*lar 5

晶体不具有.detect.find方法。(请参阅为什么

Hash正在分配堆内存,因此比case语句要慢。

您也可以尝试使用不可变的结构,例如NameTupple,非常接近case性能

     hash  46.48M ( 21.51ns) (±14.08%)  3.90× slower
nametuple 173.82M (  5.75ns) (±15.75%)  1.04× slower
     case 181.28M (  5.52ns) (±13.24%)       fastest
Run Code Online (Sandbox Code Playgroud)

水晶,450字节

     hash  46.48M ( 21.51ns) (±14.08%)  3.90× slower
nametuple 173.82M (  5.75ns) (±15.75%)  1.04× slower
     case 181.28M (  5.52ns) (±13.24%)       fastest
Run Code Online (Sandbox Code Playgroud)

在线尝试!


Joh*_*ler 5

对于在编译时已知的少量相对较小的比较值,它肯定是最快的并且(如Faustino所指出的)采用直接比较的大多数存储器效率.

这些caseNamedTuple实例基本归结为一系列x == "a" || x == "z".这很简单,意味着代码复杂度非常低,没有堆分配,快速比较.

使用散列时,每次比较都会调用散列算法(因此名称),这会增加相当多的开销.但是,散列是一种很好的数据结构,用于存储编译时未知的复杂值或动态值.

当比较较大的字符串集合时,在某些时候,简化方法不再那么有效,因为它需要比较全长的每个项目.一种更有效的方法是用于这种查找的专用数据结构,称为前缀树(有关Crystal实现,请参阅https://github.com/luislavena/radix).