Шість методів масиву Ruby, які потрібно знати

Масиви є однією з фундаментальних структур програмування. Можливість швидкого маніпулювання та зчитування даних з них є життєво важливою для успіху у створенні матеріалів за допомогою комп’ютерів. Ось шість методів, без яких не обійтися.

Карта / Кожна

Ці два методи дуже схожі. Вони дозволяють перебирати “кожен” елемент у масиві та щось робити з ним.

Перевірте якийсь код:

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

Якщо ми читаємо з added, ми отримаємо [3, 4, 5]. Якщо ми читаємо з effects, ми все одно отримаємо [1, 2, 3]. Ось різниця між цими двома: .mapповерне новий змінений масив, тоді як .eachповерне початковий масив.

Побічні ефекти на карті

Якщо ви звикли до функціонального програмування, Рубі .mapможе здатися дуже дивним. Подивіться на цей приклад. У Eventмоєму проекті є простий клас:

# we create an array of records 2.3.0 :025 > array = [e, e2, e3] => [#, #, #] # so far so good 2.3.0 :026 > new_array = array.map => [#, #, #] # uh-oh, that ain't right 2.3.0 :027 > array => [#, #, #]

Ми могли б очікувати, що ми працюємо з якоюсь копією наших записів у масиві, але ми цього не робимо. Це все лише для того, щоб сказати: будьте обережні. Ви можете легко створювати побічні ефекти у своїх .mapфункціях.

Гаразд, спокійно, це було важко. Плавне плавання звідси назовні.

Виберіть

.selectдозволяє "знайти" елемент у масиві. Вам потрібно надати .selectфункцію, яка повертає true або false, щоб вона знала, чи слід “зберігати” елемент масиву.

2.3.0 :028 > array = ['hello', 'hi', 'goodbye'] 2.3.0 :029 > array.selectword => ["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 valid_colors.include?(car[:color]) .map  => ["porsche", "prius"]

Так, люди, ви можете приєднатися до цих методів, щоб мати немислиму силу. Гаразд, ви можете це уявити, але це все одно круто.

Ще більш чистий синтаксис: .map (&: метод)

Якби ми працювали з автомобільними об'єктами, а не просто хешем, ми могли б скористатися більш чистим синтаксисом. Я буду використовувати інший приклад для стислості. Можливо, ми готуємо цей список автомобілів для надсилання в API і нам потрібно створити JSON. Ми можемо використовувати .to_jsonметод:

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

Відхилити

Відхилити - це інь до .selectян:

2.3.0 :048 > cars.reject valid_colors.include?(car[:color]) .mapcar => ["mustang"]

Замість того, щоб обирати потрібні елементи масиву, ми відкинемо все, що не робить нашу функцію поверненою істинною. Пам'ятайте, що функція всередині нашого відхилення визначає, чи буде повернутий елемент масиву чи ні - якщо це істина, елемент повертається, інакше ні.

Зменшити

Reduce має більш складну структуру, ніж наші інші методи масивів, але зазвичай він використовується для досить простих речей в Ruby - переважно математичних речей. Ми візьмемо масив, а потім запустимо функцію на кожному елементі цього масиву. Цього разу ми дбаємо про те, що повертається з інших елементів масиву . Зазвичай ми додаємо купу чисел:

2.3.0 :049 > array = [1, 2, 3] 2.3.0 :050 > array.reduce => 6

Зверніть увагу, що ми можемо працювати з рядками однаково:

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

Це може бути корисно, якщо ми переглядаємо купу робочих записів. Якщо нам потрібно скласти загальну кількість відпрацьованих годин, або якщо ми хочемо з’ясувати суму всіх пожертв минулого місяця. Останнє примітка про .reduce. Якщо ви працюєте з чимось іншим, крім звичайних старих чисел (або рядків), вам потрібно буде включити початкове значення як аргумент:

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

Звичайно, існують і більш просунуті способи використання, .reduceале цього досить для початку.

Приєднуйтесь

Я кидаю .joinяк бонус, бо це так корисно. Давайте знову скористаємось нашими машинами:

2.3.0 :061 > cars.map 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(', ') => "#, #, #"

Чому б просто не кинути все це разом

Давайте разом використаємо всі методи масивів у цій публікації! Десять днів домашніх справ, і випадково, скільки часу триватиме кожна. Ми хочемо знати загальний час, який ми витратимо на домашні справи. Це передбачає, що ми відмовляємось і ігноруємо все, що займає більше 15 хвилин. Або відкладіть на інший день все, що можна зробити менш ніж за 5:

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 .rejecttask .reduce(0)  sum + task[:minutes]

Моя відповідь неактуальна, оскільки ви отримаєте різні випадкові хвилини для виконання своїх завдань. Якщо щось із цього свіже або заплутане, запустите консоль Ruby і закрутіть її.

PS: Цей ? :бізнес .mapназивається a ternary. Це просто твердження if-else. Я використовую його тут лише для того, щоб бути фантастичним і отримувати все на «одній» лінії. Вам слід уникати такої складної трійки у власній базі коду.

Побачимось наступного разу!