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

41
我想将下面的字符串数组元素转换为符号,并输出它们。
strings = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]

看我在做什么:

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

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


2
可能是 https://dev59.com/7nRA5IYBdhLWcg3w2x2W 的重复问题。 - user1888370
1
@icktofay 我明白了,但是把它们转换成其他格式很容易,对吧? - user1888370
1
@Abe 这并不意味着它是一个重复的问题... 而且,也不完全是。你知道 Ruby 吗? - tckmn
1
@Abe:也许吧,但如果你一开始就尝试使用数组来完成它,你会得到一个更简洁的答案。 - icktoofay
对于那些说@Abe推荐的链接不适用的人,它是适用的。哈希的键就是一个数组。{'a'=>1}.keys.class => Array。问题在于你必须知道如何识别从字符串转换为符号的数组被处理的位置。 - the Tin Man
显示剩余8条评论
9个回答

59

使用map而不是each

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

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

>> strings.map &:to_sym
=> [:HTML, :CSS, :JavaScript, :Python, :Ruby]
你的each方法看起来不起作用的原因在于,调用puts输出符号的字符串表示形式(即没有:)。此外,你只是循环输出东西; 你实际上没有构建一个新数组。

34

清晰简洁的一行代码:

%w(HTML CSS JavaScript Python Ruby).map(&:to_sym)
< p >& 表示该参数应被视为一个块,即建立数组并对每个元素应用 to_sym 方法。


1
你的答案是最干净的,我还对它进行了基准测试,并在不同类型的数组上检查了其性能。我不确定是根据你的答案给出新答案还是只编辑这个答案更好。 - Lomefin

10

我会做类似于这样的事情

strings.map! &:to_sym

4

icktoofay已经给出了正确的答案。

另外一点说明:使用</p>标签

strings.map { |x| x.to_sym }

当你使用这个函数时,会得到一个新的数组,而原始数组则不会改变。

要使用它,可以将其赋值给另一个变量:

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

如果您想修改字符串,可以使用map!
strings.map! { |x| x.to_sym }

2

@icktoofay的回答是正确的,但为了帮助你更好地理解each方法,以下是如何使用each完成相同任务的方法:

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

1

如果您想采用 gem 方式,finishing_moves 有一个 Array#to_sym_strict 方法,可以完全满足您的需求:

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

还有一个#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

1

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

strings.collect {|x| x.to_sym }

我进行了一些基准测试,@cb24的答案在大多数情况下效果最好,当数组中有更多元素时,但如果它恰好是一个非常小的数组,则collect方法会稍微快一些。
我在这里发布代码和结果,这是我真正的第一个基准测试,所以如果我做错了什么,希望能得到一些反馈。我对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)

我没有计算拐点,但是很有趣。我在某个地方读到过,有些改进是通过使用短数组来实现的,因为大多数数组只有几个元素长。

0

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

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

0
为了完整起见,您还可以使用%i字符串字面量,至少从Ruby 2.0.0开始,以便从符号数组开始。
%i[HTML CSS JavaScript Python Ruby]
# => [:HTML, :CSS, :JavaScript, :Python, :Ruby]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接