Я хочу преобразовать элементы массива строк ниже в символы и вывести их
strings = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]
посмотрите, что я делаю:
strings.each { |x| puts x.to_sym }
Нет успеха. Что я делаю неправильно?
Я хочу преобразовать элементы массива строк ниже в символы и вывести их
strings = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]
посмотрите, что я делаю:
strings.each { |x| puts x.to_sym }
Нет успеха. Что я делаю неправильно?
Используйте 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
с символом выводит строковое представление символа (то есть без :
). Кроме того, вы просто просматриваете и выводите вещи; вы на самом деле не создаете новый массив.
Очистить однострочный слой:
%w(HTML CSS JavaScript Python Ruby).map(&:to_sym)
&
указывает, что аргумент следует рассматривать как блок, т.е. создавать массив и применять to_sym
к каждому элементу.
Я бы сделал что-то вроде
strings.map! &:to_sym
icktoofay уже дал правильный ответ.
Дополнительное примечание:
strings.map { |x| x.to_sym }
вы получаете новый массив, исходный массив не изменяется.
Чтобы использовать его, вы можете назначить его другой переменной:
string2 = strings.map { |x| x.to_sym }
Если вы хотите изменить строку, вы можете использовать map!
:
strings.map! { |x| x.to_sym }
@icktoofay имеет правильный ответ, но чтобы лучше понять метод each
, вот как вы можете сделать то же самое, используя each
:
strings = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]
symbols = [] # an empty array to hold our symbols
strings.each { |s| symbols << s.to_sym }
@cb24 ответ, как правило, наиболее подходящий, я хотел сравнить это решение с другим
strings.collect {|x| x.to_sym }
Я сделал некоторые тесты, а ответ @cb24 лучше всего работает в большинстве случаев, когда в массиве есть еще несколько элементов, но если это очень маленький массив, метод сбора работает немного быстрее.
Я публикую здесь код и результаты, это мой настоящий первый тест, поэтому, если у меня что-то получится, некоторые отзывы будут оценены. Я сделал это как на 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)
Точки перегиба, которые я не вычислял, но это довольно интересно, я где-то читал, что некоторые улучшения там сделаны с короткими массивами, так как большинство из них всего лишь несколько элементов.
Или может быть сделано следующим образом:
strings.each do |s|
symbols.push(s.to_sym)