В работе над массивами есть особый набор операций, который пришёл к нам из математики – это операции над множествами. В Ruby для такого случая есть специальные операторы, близкие к их математическим эквивалентам.
Представьте себе задачу поиска взаимных друзей пользователей. Для формирования такого списка на уровне кода, нужно сравнить два массива (мои друзья и друзья друга) и найти пересечение, то есть общих друзей. В данном случае массивы с друзьями — это множества, а операция поиска общих элементов – пересечение (intersection).
Пересечение на Ruby выглядит так:
friends1 = ['igor', 'anna', 'nina', 'sergey']
friends2 = ['igor', 'petya', 'inna', 'anna']
# Выглядит как побитовое И, но это пересечение
friends1 & friends2 # ["igor", "anna"]
# или
# friends1.intersection(friends2)
Такой оператор очень удобен своей естественностью. Сразу понятно, о чём идёт речь. Как и в большинстве других операторов в Ruby, мы имеем дело с вызовами методов:
friends.&(friends2)
Подобная схема позволяет не только переопределять их поведение, но и комбинировать операторы между собой:
friends = ['anna', 'ivan']
friends1 & friends2 & friends # ["anna"]
У множеств и массивов с точки зрения математики есть одно принципиальное отличие, о котором нужно помнить. Во множествах каждый элемент представлен ровно один раз (то есть все элементы — уникальны), в то время как в массивах такого ограничения не существует. Операции над множествами рассматривают массивы не как массивы, а именно как множества. Они удаляют дубли в результирующем массиве:
[1, 3, 4] & [1, 3, 3, 8] # [1, 3]
Объединение
Множество, объединяющее в себе элементы исходных множеств.
[1, 3, 4] | [1, 3, 3, 8]
# [1, 3, 4, 8]
Дополнение
Множество, состоящее из элементов первого множества, за минусом элементов, совпадающих со вторым множеством. Или по простому — это разница между двумя множествами.
# 4 – единственный элемент из первого множества, которого нет во втором
[1, 3, 4] - [1, 3, 3, 8] # [4]
Иногда в программировании возникает задача поиска разницы между двумя наборами данных, такими как объекты. Например, при поиске различий в json-файлах. Для этого даже существуют специальные сервисы, например, http://www.jsondiff.com/ (попробуйте нажать на ссылку sample data и кнопку Compare).
Реализуйте функцию gen_diff()
, которая сравнивает два объекта и возвращает результат сравнения в виде объекта. Ключами результирующего объекта будут все ключи из двух входящих объектов, а значением — строка с описанием отличий: added, deleted, changed или unchanged.
Возможные значения:
gen_diff(
{ one: 'eon', two: 'two', four: true },
{ two: 'own', zero: 4, four: true }
);
# {
# one: 'deleted',
# two: 'changed',
# four: 'unchanged',
# zero: 'added'
# }
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Ваше упражнение проверяется по этим тестам
1# frozen_string_literal: true
2
3require 'test_helper'
4require_relative 'index'
5
6describe 'function' do
7 it 'should works' do
8 actual = gen_diff(
9 { one: 'eon', two: 'two', four: true },
10 { two: 'own', zero: 4, four: true }
11 )
12
13 expected = {
14 one: 'deleted',
15 two: 'changed',
16 four: 'unchanged',
17 zero: 'added'
18 }
19
20 assert { actual == expected }
21 end
22end
23
Решение учителя откроется через: