ruby 如何将字符串数组转换为符号数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16502866/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 05:56:10  来源:igfitidea点击:

How to convert a array of strings to an array of symbols?

ruby

提问by Gracko

I want to convert the elements of the string array below to symbols, and output them

我想将下面的字符串数组的元素转换为符号,并输出它们

strings = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]

look at what I'm doing:

看看我在做什么:

strings.each { |x| puts x.to_sym }

No success. What am I doing wrong?

没有成功。我究竟做错了什么?

回答by icktoofay

Use maprather than each:

使用map而不是each

>> strings.map { |x| x.to_sym }
=> [:HTML, :CSS, :JavaScript, :Python, :Ruby]

For Ruby 1.8.7 and later or with ActiveSupport included, you can use this syntax:

对于 Ruby 1.8.7 及更高版本或包含 ActiveSupport,您可以使用以下语法:

>> strings.map &:to_sym
=> [:HTML, :CSS, :JavaScript, :Python, :Ruby]

The reason your eachmethod appears to not work is that calling putswith a symbol outputs the string representation of the symbol (that is, without the :). Additionally, you're just looping through and outputting things; you're not actually constructing a new array.

您的each方法似乎不起作用的原因是puts使用符号调用会输出符号的字符串表示形式(即,没有:)。此外,您只是循环并输出内容;你实际上并不是在构建一个新数组。

回答by cb24

Clean one-liner:

清洁单层:

%w(HTML CSS JavaScript Python Ruby).map(&:to_sym)

&tells argument should be treated as a block, i.e. build up array and apply to_symto each element.

&告诉参数应该被视为一个块,即构建数组并应用于to_sym每个元素。

回答by DaniG2k

I'd do something like

我会做类似的事情

strings.map! &:to_sym

回答by knut

icktoofay already gave the correct answer.

icktoofay 已经给出了正确答案。

On additional remark: With

补充说明:与

strings.map { |x| x.to_sym }

you get a new array, the original array is unchanged.

你得到一个新数组,原始数组不变。

To use it, you can assign it to another variable:

要使用它,您可以将它分配给另一个变量:

string2 = strings.map { |x| x.to_sym }

If you want to modify string, you can use map!:

如果要修改字符串,可以使用map!

strings.map! { |x| x.to_sym }

回答by Teddy

@icktoofay has the correct answer, but just to help you better understand the eachmethod, here is how you can do the same thing using each:

@icktoofay 有正确的答案,但只是为了帮助您更好地理解该each方法,以下是您可以使用each以下方法执行相同操作的方法:

strings = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]
symbols = [] # an empty array to hold our symbols
strings.each { |s| symbols << s.to_sym }

回答by Lomefin

@cb24's answer is generally the most appropiate, I wanted to compare that solution with another one

@cb24 的答案通常是最合适的,我想将该解决方案与另一个解决方案进行比较

strings.collect {|x| x.to_sym }

I did some benchmarks and @cb24's answer works best in most cases, when there are some more elements in the array, but if it happens to be a very tiny array, the collect method works a little faster.

我做了一些基准测试,@cb24 的答案在大多数情况下效果最好,当数组中有更多元素时,但如果它恰好是一个非常小的数组,collect 方法的工作速度会快一些。

I publish here the code and the results, this is my real first benchmark so if I got something wrong some feedback would be appreciated. I did it on both String -> Symbol and Symbol -> String

我在这里发布了代码和结果,这是我真正的第一个基准测试,所以如果我有什么问题,一些反馈将不胜感激。我在 String -> Symbol 和 Symbol -> String 上都做了

n = 1000000 

a = [:a,:b,:c,:d,:e,:f,:g,:h,:i].freeze #A "long" array of symbols

Benchmark.bm do |x|
  x.report { n.times { a.map(&:to_s)} }
  x.report { n.times { a.collect{|x| x.to_s}} }
end  

       user     system      total        real
   2.040000   0.010000   2.050000 (  2.056784)
   2.100000   0.010000   2.110000 (  2.118546)


b = [:a, :b].freeze  #Small array

Benchmark.bm do |x|
  x.report { n.times { b.map(&:to_s)} }
  x.report { n.times { b.collect{|x| x.to_s}} }
end  


       user     system      total        real
   0.610000   0.000000   0.610000 (  0.622231)
   0.530000   0.010000   0.540000 (  0.536087)



w = %w(a b).freeze  #Again, a small array, now of Strings
Benchmark.bm do |x|
  x.report { n.times { w.map(&:to_sym)} }
  x.report { n.times { w.collect{|x| x.to_sym}} }
end 

       user     system      total        real
   0.510000   0.000000   0.510000 (  0.519337)
   0.440000   0.010000   0.450000 (  0.447990)



y = %w(a b c d e f g h i j k l m n o p q).freeze #And a pretty long one
Benchmark.bm do |x|
  x.report { n.times { y.map(&:to_sym)} }
  x.report { n.times { y.collect{|x| x.to_sym}} }
end 

       user     system      total        real
   2.870000   0.030000   2.900000 (  2.928830)
   3.240000   0.030000   3.270000 (  3.371295)

The inflection points I didn't calculate but it is quite interesting, I read somewhere that some improvements where made with short arrays, since most of them are just a couple of elements long.

我没有计算拐点,但它很有趣,我在某处读到了一些使用短数组进行的改进,因为它们中的大多数只是几个元素的长度。

回答by Frank Koehl

If you want to go the gem route, finishing_moveshas an Array#to_sym_strictmethod that does exactly what you're looking for:

如果你想走 gem 路线,finishing_moves有一个Array#to_sym_strict方法可以满足你的需求:

strings = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]
strings.to_sym_strict
# => [:HTML, :CSS, :JavaScript, :Python, :Ruby]

There's also a #to_sym_looseto handle arrays of mixed type:

还有一个#to_sym_loose用于处理混合类型的数组:

strings = ["HTML", "CSS", "JavaScript", "Python", "Ruby", 1, /a regex/, {a: :hash}]
strings.to_sym_loose
# => [:HTML, :CSS, :JavaScript, :Python, :Ruby, 1, /a regex/, {a: :hash}]
# no exceptions thrown

回答by Harsha

Or can be done as follows:

或者可以按如下方式完成:

strings.each do |s|  
symbols.push(s.to_sym)