Как работает «каждая» функция в Ruby (и, следовательно, в Rails)? - PullRequest
1 голос
/ 25 сентября 2011

В книге, которую я читаю для изучения Rails (RailsSpace), автор создает две функции (ниже), чтобы превратить все названия городов с заглавными буквами, например, LOS ANGELES, в Лос-Анджелес.Однако есть кое-что, чего я не понимаю в первой функции ниже.

А именно, откуда взято слово?Я понимаю, что «слово» - это локальная / блочная переменная, которая исчезает после завершения функции, но то, что передается / присваивается «слову».Другими словами, что разделяется?

Я бы ожидал, что был какой-то аргумент, принимающий массив или хеш, переданный в эту функцию ... и затем "каждая" функция запускается над этим ..

def capitalize_each
  space = " "
  split(space).each{ |word| word.capitalize! }.join(space)     
end   

# Capitalize each word in place.     
def capitalize_each!
  replace capitalize_each end
end

Ответы [ 7 ]

5 голосов
/ 25 сентября 2011

Давайте разберемся с этим.

split(space)

превращает строку в список возможных слов.(На самом деле, если строка содержит два пробела в строке, список будет содержать пустую строку. Но это не имеет значения для этой цели.) Я предполагаю, что это метод экземпляра в String;в противном случае split не будет определено.

.each { |word| word.capitalize! }

.each берет каждую вещь в списке (возвращаемую split) и запускает следующий блок, передавая эту вещь какАрг в блок.|word| говорит, что этот блок будет называть arg "словом".Таким образом, эффективно то, что это делает, состоит в том, что каждое слово в строке пишется с заглавной буквы (и каждая пустая строка и одиночный пунктуация тоже, но, опять же, это не важно - заглавные буквы не изменяют символы, которые не имеют понятия регистра).

.join(space)

склеивает слова обратно, заново вставляя пространство, которое раньше использовалось для их разделения.Возвращаемая строка также является возвращаемым значением функции.

2 голосов
/ 25 сентября 2011

Сначала я подумал, что метод был неполным из-за отсутствия self в начале, но кажется, что даже без него split вызывается по заданной строке, space будет просто разделителем по умолчанию,Так может выглядеть метод с явным self.

class String
    def capitalize_each(separator = ' ')
        self.split(separator).each{|word| word.capitalize!}.join(separator)
    end
end

puts "LOS ANGELES".capitalize_each #=> Los Angeles
puts "LOS_ANGELES".capitalize_each('_') #=> Los_Angeles
2 голосов
/ 25 сентября 2011

Строка разделяется пробелами, то есть на слова.Таким образом, «каждый» итератор просматривает все слова, одно за другим, каждый раз, когда слово находится в объекте «слово».Итак, для этого объекта (слова) он использует для него функцию заглавных букв.Наконец, все это объединяется с Spaces.Таким образом, конечный результат является заглавным.

1 голос
/ 25 сентября 2011

Эти методы должны быть определены в классе String, поэтому разделяется любая строка, в которую вы вызываете метод capitalize_each.

Пример использования (и немного лучшая реализация):

class String
  def capitalize_each
    split(/\s+/).each{ |word| word.capitalize! }.join " " 
  end

  def capitalize_each!
    replace capitalize_each
  end
end

puts "hi, i'm a sentence".capitalize_each #=> Hi, I'm A Sentence
0 голосов
/ 26 июня 2012

Это работает, но если вы хотите превратить один массив в другой, идиоматически лучше использовать map вместо each, например:

words.map{|word|word.capitalize}

(Без завершающего !, capitalize создает новую строку вместо изменения старой строки, а map собирает эти новые строки в новый массив. Напротив, each возвращает старый массив.)

Или, следуя примеру Ганна:

class String
  def capitalize_each
    self.split(/\s/).map{|word|word.capitalize}.join(' ')
  end
end

"foo bar  baz".capitalize_each #=> "Foo Bar  Baz"

по умолчанию split разделяется на строки пробелов, но, передавая регулярное выражение, оно соответствует каждому отдельным пробелам, даже если они в строке. *

0 голосов
/ 25 сентября 2011

Если вы имеете в виду, как он попадает в ваш блок, то он уступает блоку. #split возвращает массив, и метод #each делает что-то вроде:

for object in stored_objects
  yield object
end
0 голосов
/ 25 сентября 2011

Думайте о |word| word.capitalize! как о функции , которую вы переходите в метод each.Функция имеет один аргумент (word) и просто оценивает .capitalize!.

Теперь, что делает метод each, берет каждый элемент в split(space) и оценивает вашу функцию по нему.Итак:

"abcd".each{|x| print x}

будет оценивать, по порядку, print "a", print "b", print "c".

http://www.ruby -doc.org / core / classes / Array.html # M000231

Чтобы немного демистифицировать это поведение, оно помогает точно понять, что оно означает«принять каждый элемент в __».По сути, любой объект, который является перечисляемым , может быть .each редактирован таким образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...