Шесть методов массива Ruby, которые вам нужно знать

shest metodov massiva ruby kotorye vam nuzhno znat

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

Карта/каждая

Эти два метода очень схожи. Они позволяют вам переходить по «каждому» элементу в массиве и делать с ним что-нибудь.

Просмотрите код:

array = [1, 2, 3]
effects = array.each{|x| # create record from x }
added = array.map{ |x| x + 2 }

Если читать с addedмы получим [3, 4, 5]. Если читать с effectsмы еще получим [1, 2, 3]. Вот разница между этими двумя: .map вернется a новый измененный массив, тогда как .each вернет исходный массив.

Побочные эффекты в карте

Если вы привыкли к функциональному программированию, Ruby’s .map может показаться очень странным. Посмотрите на этот пример. У меня простой Event класс в моем проекте:

# we create an array of records
2.3.0 :025 > array = [e, e2, e3]
 => [#<Event id: 1, name: nil>, #<Event id: 2, name: nil">, #<Event id: 3, name: nil>]
# so far so good
2.3.0 :026 > new_array = array.map{|e| e.name = "a name"; e}
 => [#<Event id: 1, name: "a name">, #<Event id: 2, name: "a name">, #<Event id: 3, name: "a name">]
# uh-oh, that ain't right
2.3.0 :027 > array
 => [#<Event id: 1, name: "a name">, #<Event id: 2, name: "a name">, #<Event id: 3, name: "a name">]

Мы могли бы ожидать, что мы работаем с копией наших записей в массиве, но это не так. Это все, чтобы сказать: будьте осторожны. Вы можете легко создать побочные эффекты в своем .map функции.

Ладно, спокойно, это было тяжело. Плавное плавание отсюда и дальше.

Выберите

.select позволяет «найти» элемент в массиве. Вы должны отдать .select функция, возвращающая true или false, поэтому она знает, «сохранять» ли элемент массива.

2.3.0 :028 > array = ['hello', 'hi', 'goodbye']
2.3.0 :029 > array.select{|word| word.length > 3}
 => ["hello", "goodbye"]

Несколько более сложный пример, который, вероятно, приближается к тому, как бы вы на самом деле это использовали. Вбрасываем .map в конце для хорошей степени:

2.3.0 :030 > valid_colors = ['red', 'green', 'blue']
2.3.0 :031 > cars = [{type: 'porsche', color: 'red'}, {type: 'mustang', color: 'orange'}, {type: 'prius', color: 'blue'}]
2.3.0 :032 > cars.select{ |car| valid_colors.include?(car[:color]) }.map{ |car| car[:type]}
=> ["porsche", "prius"]

Да, люди, вы можете присоединиться к этим методам, чтобы получить невероятную силу. Ладно, вы, наверное, можете себе представить, но это все равно круто.

Еще более чистый синтаксис: .map(&:method)

Если бы мы работали с объектами автомобиля, а не просто с простым хэшем, мы могли бы использовать более чистый синтаксис. Для краткости я использую другой пример. Возможно, мы готовим этот список автомобилей для отправки через API, и нам нужно сгенерировать JSON. Мы можем использовать .to_json метод:

# using regular map syntax
2.3.0 :047 > cars.select{ |car| valid_colors.include?(car[:color]) }.map{|car| car.to_json}
 => ["{\"type\":\"porsche\",\"color\":\"red\"}", "{\"type\":\"prius\",\"color\":\"blue\"}"]
# using the cleaner syntax
2.3.0 :046 > cars.select{|car| valid_colors.include?(car[:color]) }.map(&:to_json)
 => ["{\"type\":\"porsche\",\"color\":\"red\"}", "{\"type\":\"prius\",\"color\":\"blue\"}"]

Отклонять

Отбросить – это инь к .select‘s yang:

2.3.0 :048 > cars.reject{|car| valid_colors.include?(car[:color]) }.map{|car| car[:type]}
 => ["mustang"]

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

Уменьшить

Reduce имеет более сложную структуру, чем наши другие методы массивов, но обычно используется для довольно простых вещей у Ruby — преимущественно математических. Мы возьмем массив, затем запустим функцию для каждого элемента этого массива. На этот раз мы заботимся о том, что возвращается из другие элементы массива. Обычно мы составляем кучу чисел:

2.3.0 :049 > array = [1, 2, 3]
2.3.0 :050 > array.reduce{|sum, x| sum + x}
 => 6

Обратите внимание, что мы можем работать со строчками таким же образом:

2.3.0 :053 > array = ['amber', 'scott', 'erica']
2.3.0 :054 > array.reduce{|sum, name| sum + name}
 => "amberscotterica"

Это может быть полезно, если мы просматриваем кучу рабочих записей. Если нам нужно добавить общее количество отработанных часов или если мы хотим узнать сумму всех пожертвований в прошлом месяце. Последнее замечание о .reduce. Если вы работаете с чем-то другим, кроме обычных старых чисел (или строк), вам нужно будет включить исходное значение в качестве аргумента:

array = [{weekday: 'Monday', pay: 123}, {weekday: 'Tuedsay', pay: 244}]
array.reduce(0) {|sum, day| sum + day[:pay]}
 => 367
array.reduce(100) {|sum, day| sum + day[:pay]}
 => 467

Есть, конечно, и более продвинутые способы использования .reduce но этого достаточно, чтобы начать.

Присоединяйтесь

Я бросаю .join как бонус, потому что это очень полезно. Давайте снова использовать наши машины:

2.3.0 :061 > cars.map{|car| car[:type]}.join(', ')
 => "porsche, mustang, prius"

.join очень похоже .reduce за исключением того, что у него чрезвычайно чистый синтаксис. Он принимает один аргумент: строка, которая будет вставлена ​​между всеми элементами массива. .joinсоздает одну длинную строчку из всего, что вы ему предоставляете, даже если ваш массив состоит из кучи нестрочных вещей:

2.3.0 :062 > cars.join(', ')
 => "{:type=>\"porsche\", :color=>\"red\"}, {:type=>\"mustang\", :color=>\"orange\"}, {:type=>\"prius\", :color=>\"blue\"}"
2.3.0 :065 > events.join(', ')
 => "#<Event:0x007f9beef84a08>, #<Event:0x007f9bf0165e70>, #<Event:0x007f9beb5b9170>"

Почему бы просто не собрать все вместе

Давайте использовать все методов массива в этой публикации вместе! Десять дней домашних дел и это случайно, сколько времени займет каждый. Мы хотим знать общее время, которое мы потратим на работу по дому. Это предполагает, что мы расслабимся и игнорируем все, что занимает более 15 минут. Или отложите на другой день все, что можно сделать менее чем за пять.

days = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
days.map{|day| day.odd? ? 
  {task: 'dishes', minutes: Random.rand(20)} :
  {task: 'sweep', minutes: Random.rand(20)}}
  .select{|task| task[:minutes] < 15}
  .reject{|task| task[:minutes] < 5}
  .reduce(0) {|sum, task| sum + task[:minutes]}

Мой ответ не имеет значения, потому что вы получите разные случайные минуты для своих задач. Если что-нибудь из этого свежее или запутано, запустите консоль Ruby и попробуйте ее.

PS: Это ? : бизнес на .map называется a ternary. Это просто оператор if-else. Я использую его здесь только для того, чтобы показать все на одной линии. Вам следует избегать такого сложного троичного кода в вашей базе кода.

Увидимся в следующий раз!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *