当用符号代替的字符串在Ruby中?(When to use symbols instead of s

2019-09-04 05:16发布

如果有相同的字符串的至少两个实例在我的剧本,我应该改为使用符号?

Answer 1:

TL; DR

一条简单的拇指法则是用符号每次需要内部标识符的时间。 为Ruby <2.2只使用符号时动态地不产生它们,以避免内存泄漏。

完整的答案

不将其用于动态生成的标识符的唯一原因是因为内存的担忧。

这个问题是很常见的,因为很多的编程语言都没有符号,只是字符串,因此字符串也被用作在你的代码标识。 你应该担心什么符号的意思是 ,不仅当你应该使用的符号 。 符号意思是标识符。 如果按照这个理念,有机会,你会做正确的事情。

有符号和字符串的执行之间的一些差异。 关于符号的最重要的事情是,他们是不可变的 。 这意味着,他们将永远不会有自己的价值变化。 正因为如此,符号实例不是字符串和一些操作比较喜欢两个符号要快也快。

一个符号是不可改变的事实允许红宝石使用每次引用符号,节省内存时相同的对象。 所以每次解释读取时间:my_key它可以把它从内存中,而不是再次实例化。 这是不是每次初始化一个新的字符串便宜。

你可以得到一个列表已经与命令实例化的所有符号Symbol.all_symbols

symbols_count = Symbol.all_symbols.count # all_symbols is an array with all 
                                         # instantiated symbols. 
a = :one
puts a.object_id
# prints 167778 

a = :two
puts a.object_id
# prints 167858

a = :one
puts a.object_id
# prints 167778 again - the same object_id from the first time!

puts Symbol.all_symbols.count - symbols_count
# prints 2, the two objects we created.

对于2.2之前版本的Ruby,一旦符号被实例化,这种记忆将永远不会再次释放 。 释放内存的唯一方法是重新启动应用程序。 因此,不正确使用时,符号也内存泄漏的主要原因。 以产生一内存泄漏的最简单的方法是使用该方法to_sym上的用户输入数据,因为该数据将总是改变,所述存储器的一个新的部分将永远在软件实例中使用。 红宝石2.2引入的符号垃圾收集器 ,从而释放动态生成的码元,所以通过创建符号产生的内存泄漏动态它不是一个问题的任何更长的时间。

回答你的问题:

难道我必须用一个字符串的符号代替,如果有至少两个在我的应用程序或脚本的相同字符串?

如果你正在寻找的是一个标识符是在你的代码在内部使用,你应该用符号。 如果您在打印输出时,你应该用绳子走,即使出现了不止一次,甚至在内存中分配两个不同的对象。

这里的推理:

  1. 打印符号会比打印字符串,因为它们转换为字符串慢。
  2. 有许多不同的符号会增加你的应用程序的整体内存使用,因为它们是永远不会释放。 你永远不会使用从您的代码中的所有字符串在同一时间。

通过@AlanDert使用情况

@AlanDert:如果我用很多次类似%输入{类型:复选框}在HAML代码,我应该为复选框使用?

我可以。

@AlanDert:但打印出来的HTML页面上的符号,应该转换成字符串,不应该吗? 什么是使用它,然后点?

什么是输入的类型? 要使用或要显示给用户的东西输入的类型的标识?

这是事实,这将成为在某一时刻的HTML代码,但此刻的你正在编写一行代码,它是意味着是一个标识符 - 它确定你需要什么样的输入栏。 因此,它是用来一遍又一遍在你的代码,并一直字符的标识符相同的“串”,并且不会产生内存泄漏。

这就是说,我们为什么不评估,看是否字符串是更快的数据?

这是一个简单的基准我为这个创建的:

require 'benchmark'
require 'haml'

str = Benchmark.measure do
  10_000.times do
    Haml::Engine.new('%input{type: "checkbox"}').render
  end
end.total

sym = Benchmark.measure do
  10_000.times do
    Haml::Engine.new('%input{type: :checkbox}').render
  end
end.total

puts "String: " + str.to_s
puts "Symbol: " + sym.to_s

三路输出:

# first time
String: 5.14
Symbol: 5.07
#second
String: 5.29
Symbol: 5.050000000000001
#third
String: 4.7700000000000005
Symbol: 4.68

因此,使用smbols实际上比使用字符串快一点。 这是为什么? 这取决于HAML的实现方式。 我需要破解的HAML代码有点看,但如果你保持一个标识符的概念使用的符号,你的应用程序会更快,可靠。 当问题罢工,基准,并得到你的答案。



Answer 2:

简单地说,一个符号是一个名字,字符组成,但不可改变的。 一个字符串,相反,是人物,其内容是允许更改有序的容器。



Answer 3:

  1. 一个Ruby符号是O(1)的比较对象

比较两个字符串,我们可能需要看每个字符。 对于长度为N的两个字符串,这将需要N + 1比较(其中计算机科学家称之为“O(N)时间”)。

def string_comp str1, str2
  return false if str1.length != str2.length
  for i in 0...str1.length
    return false if str1[i] != str2[i]
  end
  return true
end
string_comp "foo", "foo"

但是,由于每一个外观:富指的是同一个对象,我们可以通过观察对象ID比较符号。 我们可以用比较单一(其中计算机科学家称之为“O(1)时间”)做到这一点。

def symbol_comp sym1, sym2
  sym1.object_id == sym2.object_id
end
symbol_comp :foo, :foo
  1. Ruby的符号是自由格式枚举的标签

在C ++中,我们可以用“枚举”来表示相关常量的家庭:

enum BugStatus { OPEN, CLOSED };
BugStatus original_status = OPEN;
BugStatus current_status  = CLOSED;

但是,因为Ruby是一种动态语言,我们不用担心声明BugStatus类型,或跟踪的合法值。 取而代之的是,我们所代表的枚举值符号:

original_status = :open
current_status  = :closed

3.A Ruby的符号是一个常量,唯一的名称

在Ruby中,我们可以改变一个字符串的内容:

"foo"[0] = ?b # "boo"

但是,我们不能改变一个符号的内容:

:foo[0]  = ?b # Raises an error
  1. 一个Ruby符号为关键字参数关键字

当传递关键字参数到一个Ruby功能,我们用符号指定关键字:

# Build a URL for 'bug' using Rails.
url_for :controller => 'bug',
        :action => 'show',
        :id => bug.id
  1. Ruby的符号是一个散列键的最佳选择

通常情况下,我们将用符号来代表一个哈希表的键:

options = {}
options[:auto_save]     = true
options[:show_comments] = false


Answer 4:

这里是一个不错的字符串VS符号基准我发现在Codecademy网站:

require 'benchmark'

string_AZ = Hash[("a".."z").to_a.zip((1..26).to_a)]
symbol_AZ = Hash[(:a..:z).to_a.zip((1..26).to_a)]

string_time = Benchmark.realtime do
  1000_000.times { string_AZ["r"] }
end

symbol_time = Benchmark.realtime do
  1000_000.times { symbol_AZ[:r] }
end

puts "String time: #{string_time} seconds."
puts "Symbol time: #{symbol_time} seconds."

输出是:

String time: 0.21983 seconds.
Symbol time: 0.087873 seconds.


Answer 5:

  • 使用符号作为哈希键标识

    {key: "value"}

  • 符号,您可以调用该方法以不同的顺序

     def write(file:, data:, mode: "ascii")
          # removed for brevity
     end
     write(data: 123, file: "test.txt")
  • 冻结,以保持作为一个字符串,并节省内存

    label = 'My Label'.freeze



文章来源: When to use symbols instead of strings in Ruby?
标签: ruby symbols