diff --git a/1-js/05-data-types/07-map-set/01-array-unique-map/_js.view/test.js b/1-js/05-data-types/07-map-set/01-array-unique-map/_js.view/test.js index cfc7b1fc3..dd147d151 100644 --- a/1-js/05-data-types/07-map-set/01-array-unique-map/_js.view/test.js +++ b/1-js/05-data-types/07-map-set/01-array-unique-map/_js.view/test.js @@ -1,5 +1,5 @@ describe("unique", function() { - it("removes non-unique elements", function() { + it("видалити не унікальні елементи", function() { let strings = ["Hare", "Krishna", "Hare", "Krishna", "Krishna", "Krishna", "Hare", "Hare", ":-O" ]; @@ -7,7 +7,7 @@ describe("unique", function() { assert.deepEqual(unique(strings), ["Hare", "Krishna", ":-O"]); }); - it("does not change the source array", function() { + it("не змінювати вихідний масив", function() { let strings = ["Krishna", "Krishna", "Hare", "Hare"]; unique(strings); assert.deepEqual(strings, ["Krishna", "Krishna", "Hare", "Hare"]); diff --git a/1-js/05-data-types/07-map-set/01-array-unique-map/task.md b/1-js/05-data-types/07-map-set/01-array-unique-map/task.md index d68030032..1c2a61acb 100644 --- a/1-js/05-data-types/07-map-set/01-array-unique-map/task.md +++ b/1-js/05-data-types/07-map-set/01-array-unique-map/task.md @@ -2,17 +2,17 @@ importance: 5 --- -# Filter unique array members +# Фільтрувати унікальні елементи масиву -Let `arr` be an array. +Нехай `arr` - це масив. -Create a function `unique(arr)` that should return an array with unique items of `arr`. +Потрібно створити функцію `unique(arr)`, яка повинна повертати масив унікальних елементів `arr`. -For instance: +Наприклад: ```js function unique(arr) { - /* your code */ + /* Твій код */ } let values = ["Hare", "Krishna", "Hare", "Krishna", @@ -22,6 +22,6 @@ let values = ["Hare", "Krishna", "Hare", "Krishna", alert( unique(values) ); // Hare, Krishna, :-O ``` -P.S. Here strings are used, but can be values of any type. +P.S. В прикладі ми використали рядки, але можуть бути значення будь-якого типу. -P.P.S. Use `Set` to store unique values. +P.P.S. Використайте `Set` для формування множини унікальних значень. diff --git a/1-js/05-data-types/07-map-set/02-filter-anagrams/_js.view/test.js b/1-js/05-data-types/07-map-set/02-filter-anagrams/_js.view/test.js index 75acb36b7..74accad4b 100644 --- a/1-js/05-data-types/07-map-set/02-filter-anagrams/_js.view/test.js +++ b/1-js/05-data-types/07-map-set/02-filter-anagrams/_js.view/test.js @@ -2,9 +2,9 @@ function intersection(arr1, arr2) { return arr1.filter(item => arr2.includes(item)); } -describe("aclean", function() { +describe("aclean", function () { - it("returns exactly 1 word from each anagram set", function() { + it("повертає тільки 1 слово для кожного набору анаграм", function () { let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"]; let result = aclean(arr); @@ -16,7 +16,7 @@ describe("aclean", function() { }); - it("is case-insensitive", function() { + it("не враховує регістр", function () { let arr = ["era", "EAR"]; assert.equal(aclean(arr).length, 1); }); diff --git a/1-js/05-data-types/07-map-set/02-filter-anagrams/solution.md b/1-js/05-data-types/07-map-set/02-filter-anagrams/solution.md index 160675185..c80d45c2f 100644 --- a/1-js/05-data-types/07-map-set/02-filter-anagrams/solution.md +++ b/1-js/05-data-types/07-map-set/02-filter-anagrams/solution.md @@ -1,6 +1,6 @@ -To find all anagrams, let's split every word to letters and sort them. When letter-sorted, all anagrams are same. +Щоб знайти всі анаграми, давайте розіб'ємо кожне слово на літери і відсортуємо їх, а потім об'єднаємо масив знову в рядок. Після цього всі анаграми будуть однакові. -For instance: +Наприклад: ``` nap, pan -> anp @@ -9,14 +9,14 @@ cheaters, hectares, teachers -> aceehrst ... ``` -We'll use the letter-sorted variants as map keys to store only one value per each key: +Ми будемо використовувати відсортовані рядки як ключі в колекції Map, для того щоб зіставити кожному ключу тільки одне значення: ```js run function aclean(arr) { let map = new Map(); for (let word of arr) { - // split the word by letters, sort them and join back + // розділіть слово на літери, відсортуйте їх та знову з'єднайте *!* let sorted = word.toLowerCase().split('').sort().join(''); // (*) */!* @@ -31,9 +31,9 @@ let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"]; alert( aclean(arr) ); ``` -Letter-sorting is done by the chain of calls in the line `(*)`. +Сортування літер здійснюється ланцюжком викликів одним рядком `(*)`. -For convenience let's split it into multiple lines: +Для зручності давайте розіб'ємо на декілька рядків: ```js let sorted = word // PAN @@ -43,21 +43,21 @@ let sorted = word // PAN .join(''); // anp ``` -Two different words `'PAN'` and `'nap'` receive the same letter-sorted form `'anp'`. +Два різних слова `'PAN'` і `'nap'` приймають ту ж саму форму після сортування букв - `'anp'`. -The next line put the word into the map: +Наступна лінія поміщає слово в об'єкт `Map`: ```js map.set(sorted, word); ``` -If we ever meet a word the same letter-sorted form again, then it would overwrite the previous value with the same key in the map. So we'll always have at maximum one word per letter-form. +Якщо ми коли-небудь ще зустрінемо слово в тій же відсортованої формі, тоді це слово перезапише значення з тим же ключем в об'єкті. Таким чином, декільком словами у нас буде завжди відповідати одна відсортована форма. -At the end `Array.from(map.values())` takes an iterable over map values (we don't need keys in the result) and returns an array of them. +Врешті-решт `Array.from(map.values())` приймає значення об'єкта-ітератора 'Map' (в цьому випадку нам не потрібні ключі) і повертає їх у вигляді масиву. -Here we could also use a plain object instead of the `Map`, because keys are strings. +Тут ми також можемо використовувати звичайний об'єкт замість `Map`, тому що ключі - це рядки. -That's how the solution can look: +Ось один з варіантів рішень задачі: ```js run demo function aclean(arr) { diff --git a/1-js/05-data-types/07-map-set/02-filter-anagrams/task.md b/1-js/05-data-types/07-map-set/02-filter-anagrams/task.md index 731fd2c25..0ba78ec0f 100644 --- a/1-js/05-data-types/07-map-set/02-filter-anagrams/task.md +++ b/1-js/05-data-types/07-map-set/02-filter-anagrams/task.md @@ -2,11 +2,11 @@ importance: 4 --- -# Filter anagrams +# Відфільтруйте анаграми -[Anagrams](https://en.wikipedia.org/wiki/Anagram) are words that have the same number of same letters, but in different order. +[Анаграми](https://en.wikipedia.org/wiki/Anagram) -- це слова, у яких ті ж букви в тій же кількості, але вони розташовуються в іншому порядку. -For instance: +Наприклад: ``` nap - pan @@ -14,9 +14,9 @@ ear - are - era cheaters - hectares - teachers ``` -Write a function `aclean(arr)` that returns an array cleaned from anagrams. +Напишіть функцію `aclean(arr)`, яка повертає масив без анаграм. -For instance: +Наприклад: ```js let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"]; @@ -24,5 +24,5 @@ let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"]; alert( aclean(arr) ); // "nap,teachers,ear" or "PAN,cheaters,era" ``` -From every anagram group should remain only one word, no matter which one. +З кожної групи анаграм має залишитися тільки одне слово, не має значення яке. diff --git a/1-js/05-data-types/07-map-set/03-iterable-keys/solution.md b/1-js/05-data-types/07-map-set/03-iterable-keys/solution.md index 7310d1d36..33730a6fa 100644 --- a/1-js/05-data-types/07-map-set/03-iterable-keys/solution.md +++ b/1-js/05-data-types/07-map-set/03-iterable-keys/solution.md @@ -1,7 +1,7 @@ -That's because `map.keys()` returns an iterable, but not an array. +Ми отримали помилку тому, що `map.keys()` повертає об'єкт-ітератор, а не масив. -We can convert it into an array using `Array.from`: +Ми можемо конвертувати його використовуючи `Array.from`: ```js run diff --git a/1-js/05-data-types/07-map-set/03-iterable-keys/task.md b/1-js/05-data-types/07-map-set/03-iterable-keys/task.md index 81507647f..8cb89fdaa 100644 --- a/1-js/05-data-types/07-map-set/03-iterable-keys/task.md +++ b/1-js/05-data-types/07-map-set/03-iterable-keys/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Iterable keys +# Перебираємо ключі -We'd like to get an array of `map.keys()` in a variable and then apply array-specific methods to it, e.g. `.push`. +Ми хотіли б отримати масив ключів `map.keys()` в змінну і далі працювати з ними, наприклад, застосувати метод `.push`. -But that doesn't work: +Але так не спрацює: ```js run let map = new Map(); @@ -16,9 +16,9 @@ map.set("name", "John"); let keys = map.keys(); *!* -// Error: keys.push is not a function +// Помилка: keys.push -- це не функція keys.push("more"); */!* ``` -Why? How can we fix the code to make `keys.push` work? +Чому? Що потрібно виправити в коді, щоб `keys.push` працював? diff --git a/1-js/05-data-types/07-map-set/article.md b/1-js/05-data-types/07-map-set/article.md index bd6cad562..5dc6644e5 100644 --- a/1-js/05-data-types/07-map-set/article.md +++ b/1-js/05-data-types/07-map-set/article.md @@ -1,170 +1,170 @@ -# Map and Set +# Map і Set -Till now, we've learned about the following complex data structures: +Зараз ми знаємо про наступні складні структури даних: -- Objects are used for storing keyed collections. -- Arrays are used for storing ordered collections. +- Об’єкти для зберігання іменованих колекцій. +- Масиви для зберігання впорядкованих колекцій. -But that's not enough for real life. That's why `Map` and `Set` also exist. +Але цього не завжди достатньо в реальному житті. Ось чому існують `Map` і `Set`. ## Map -[Map](mdn:js/Map) is a collection of keyed data items, just like an `Object`. But the main difference is that `Map` allows keys of any type. +[Map](mdn:js/Map) це колекція ключ/значення, як і `Object`. Але основна відмінність полягає в тому, що `Map` дозволяє мати ключі будь-якого типу. -Methods and properties are: +Методи та властивості: -- `new Map()` -- creates the map. -- `map.set(key, value)` -- stores the value by the key. -- `map.get(key)` -- returns the value by the key, `undefined` if `key` doesn't exist in map. -- `map.has(key)` -- returns `true` if the `key` exists, `false` otherwise. -- `map.delete(key)` -- removes the value by the key. -- `map.clear()` -- removes everything from the map. -- `map.size` -- returns the current element count. +- `new Map()` -- створює колекцію. +- `map.set(key, value)` -- зберігає значення `value` за ключем `key`. +- `map.get(key)` -- повертає значення за ключем; повертає `undefined` якщо `key` немає в колекції. +- `map.has(key)` -- повертає `true` якщо `key` існує, інакше `false`. +- `map.delete(key)` -- видаляє елемент по ключу. +- `map.clear()` -- видаляє всі елементи колекції. +- `map.size` -- повертає поточну кількість елементів. -For instance: +Наприклад: ```js run let map = new Map(); -map.set('1', 'str1'); // a string key -map.set(1, 'num1'); // a numeric key -map.set(true, 'bool1'); // a boolean key +map.set('1', 'str1'); // рядок як ключ +map.set(1, 'num1'); // цифра як ключ +map.set(true, 'bool1'); // булеве значення як ключ -// remember the regular Object? it would convert keys to string -// Map keeps the type, so these two are different: +// пам’ятаєте звичайний об’єкт `Object`? Він перетворює всі ключі в рядок +// Map зберігає тип ключів, так що в цьому випадку ми отримаємо 2 різних значення: alert( map.get(1) ); // 'num1' alert( map.get('1') ); // 'str1' alert( map.size ); // 3 ``` -As we can see, unlike objects, keys are not converted to strings. Any type of key is possible. +Як ми бачимо, на відміну від об’єктів, ключі не були приведені до рядків. Можна використовувати будь-які типи даних для ключів. -```smart header="`map[key]` isn't the right way to use a `Map`" -Although `map[key]` also works, e.g. we can set `map[key] = 2`, this is treating `map` as a plain JavaScript object, so it implies all corresponding limitations (only string/symbol keys and so on). +```smart header="`map[key]` не є правильним методом використання `Map`" +Хоча `map[key]` також працює, але такий спосіб присвоєння `map[key] = 2` використовує колекцію як звичайний JavaScript об’єкт, тобто накладає відповідні обмеження (тільки типи рядки/символи як ключі та інше). -So we should use `map` methods: `set`, `get` and so on. +Таким чином ми повинні користуватись `map` методами: `set`, `get` і так далі. ``` -**Map can also use objects as keys.** +**Map також може використовувати об’єкти як ключі.** -For instance: +Наприклад: ```js run let john = { name: "John" }; -// for every user, let's store their visits count +// збережімо кількість відвідувань для кожного користувача let visitsCountMap = new Map(); -// john is the key for the map +// об’єкт john -- це ключ для значення в колекції Map visitsCountMap.set(john, 123); alert( visitsCountMap.get(john) ); // 123 ``` -Using objects as keys is one of the most notable and important `Map` features. The same does not count for `Object`. String as a key in `Object` is fine, but we can't use another `Object` as a key in `Object`. +Об’єкти в якості ключів -- це одна з відомих можливостей колекції `Map`, яку часто використовують. У звичайному об’єкті `Object`, ми можемо використати ключі-рядки, проте ключі-об’єкти -- вже ні. -Let's try: +Розгляньмо такий приклад: ```js run let john = { name: "John" }; let ben = { name: "Ben" }; -let visitsCountObj = {}; // try to use an object +let visitsCountObj = {}; // оголосимо звичайний об’єкт -visitsCountObj[ben] = 234; // try to use ben object as the key -visitsCountObj[john] = 123; // try to use john object as the key, ben object will get replaced +visitsCountObj[ben] = 234; // використаємо об’єкт `ben` як ключ +visitsCountObj[john] = 123; // використаємо `john` об’єкт як ключ, `ben` об’єкт буде перезаписаний *!* -// That's what got written! -alert( visitsCountObj["[object Object]"] ); // 123 +// Ось як це було записано! +alert( visitsCountObj["[object Object]"] ); // 123 */!* ``` -As `visitsCountObj` is an object, it converts all `Object` keys, such as `john` and `ben` above, to same string `"[object Object]"`. Definitely not what we want. +Оскільки `visitsCountObj` -- це об’єкт, він конвертує всі ключі типу `Object` (такі як `john` і `ben`) до рядка `"[object Object]"`. Це однозначно не той результат, який ми очікуємо. -```smart header="How `Map` compares keys" -To test keys for equivalence, `Map` uses the algorithm [SameValueZero](https://tc39.github.io/ecma262/#sec-samevaluezero). It is roughly the same as strict equality `===`, but the difference is that `NaN` is considered equal to `NaN`. So `NaN` can be used as the key as well. +```smart header="Як `Map` порівнює ключі" +Порівнюючи ключі, об’єкт `Map` використовує алгоритм [SameValueZero](https://tc39.github.io/ecma262/#sec-samevaluezero). Це майже таке ж порівняння, що і `===`, з тією лише різницею, що `NaN` вважається рівним `NaN`. Таким чином `NaN` може також бути використаний як ключ. -This algorithm can't be changed or customized. +Цей алгоритм не може бути замінений або модифікований. ``` -````smart header="Chaining" -Every `map.set` call returns the map itself, so we can "chain" the calls: +````smart header="Послідовні виклики" +Кожен виклик `map.set` повертає об’єкт map, таким чином ми можемо об’єднати виклики в ланцюжок: ```js map.set('1', 'str1') - .set(1, 'num1') - .set(true, 'bool1'); +.set(1, 'num1') +.set(true, 'bool1'); ``` ```` -## Iteration over Map +## Перебір Map -For looping over a `map`, there are 3 methods: +Для перебору колекції Map є 3 метода: -- `map.keys()` -- returns an iterable for keys, -- `map.values()` -- returns an iterable for values, -- `map.entries()` -- returns an iterable for entries `[key, value]`, it's used by default in `for..of`. +- `map.keys()` -- повертає об’єкт-ітератор для ключів, +- `map.values()` -- повертає об’єкт-ітератор для значень, +- `map.entries()` -- повертає об’єкт-ітератор зі значеннями виду [ключ, значення], цей варіант використовується за умовчанням у `for..of`. -For instance: +Наприклад: ```js run let recipeMap = new Map([ - ['cucumber', 500], - ['tomatoes', 350], - ['onion', 50] +['cucumber', 500], +['tomatoes', 350], +['onion', 50] ]); -// iterate over keys (vegetables) +// перебираємо ключі (овочі) for (let vegetable of recipeMap.keys()) { alert(vegetable); // cucumber, tomatoes, onion } -// iterate over values (amounts) +// перебираємо значення (числа) for (let amount of recipeMap.values()) { alert(amount); // 500, 350, 50 } -// iterate over [key, value] entries -for (let entry of recipeMap) { // the same as of recipeMap.entries() - alert(entry); // cucumber,500 (and so on) +// перебір елементів у форматі [ключ, значення] +for (let entry of recipeMap) { // те ж саме, що recipeMap.entries() + alert(entry); // cucumber,500 (і так далі) } ``` -```smart header="The insertion order is used" -The iteration goes in the same order as the values were inserted. `Map` preserves this order, unlike a regular `Object`. +```smart header="Використовується порядок вставки" +На відміну від звичайних об’єктів `Object`, в `Map` перебір відбувається в тому ж порядку, в якому відбувалося додавання елементів. ``` -Besides that, `Map` has a built-in `forEach` method, similar to `Array`: +Крім цього, `Map` має вбудований метод `forEach`, схожий з вбудованим методом масивів `Array`: ```js -// runs the function for each (key, value) pair +// виконуємо функцію для кожної пари (ключ, значення) recipeMap.forEach( (value, key, map) => { - alert(`${key}: ${value}`); // cucumber: 500 etc + alert(`${key}: ${value}`); // cucumber: 500 і так далі }); ``` -## Object.entries: Map from Object +## Object.entries: Map з Object -When a `Map` is created, we can pass an array (or another iterable) with key/value pairs for initialization, like this: +При створенні `Map` ми можемо вказати масив (або інший об’єкт-ітератор) з парами ключ-значення для ініціалізації, як тут: ```js run -// array of [key, value] pairs +// масив пар [ключ, значення] let map = new Map([ ['1', 'str1'], [1, 'num1'], - [true, 'bool1'] +[true, 'bool1'] ]); alert( map.get('1') ); // str1 ``` -If we have a plain object, and we'd like to create a `Map` from it, then we can use built-in method [Object.entries(obj)](mdn:js/Object/entries) that returns an array of key/value pairs for an object exactly in that format. +Якщо у нас вже є звичайний об’єкт, і ми хотіли б створити `Map` з нього, то допоможе вбудований метод [Object.entries(obj)](mdn:js/Object/entries) який отримує об’єкт і повертає масив пар ключ-значення для нього, як раз в цьому форматі. -So we can create a map from an object like this: +Таким чином ми можемо створити `Map` з об’єкта наступним чином: ```js run let obj = { @@ -179,20 +179,20 @@ let map = new Map(Object.entries(obj)); alert( map.get('name') ); // John ``` -Here, `Object.entries` returns the array of key/value pairs: `[ ["name","John"], ["age", 30] ]`. That's what `Map` needs. +В цьому випадку `Object.entries` повертає масив пар ключ-значення: `[ ["name","John"], ["age", 30] ]`. Це саме те, що потрібно для створення `Map`. -## Object.fromEntries: Object from Map +## Object.fromEntries: Object з Map -We've just seen how to create `Map` from a plain object with `Object.entries(obj)`. +Ми щойно створювали `Map` з простого об’єкта за допомогою `Object.entries(obj)`. -There's `Object.fromEntries` method that does the reverse: given an array of `[key, value]` pairs, it creates an object from them: +Ми можемо використати `Object.fromEntries` метод, який виконає зворотну дію: трансформує отриманий масив пар `[ключ, значення]` в об’єкт. Наприклад: ```js run let prices = Object.fromEntries([ - ['banana', 1], - ['orange', 2], - ['meat', 4] +['banana', 1], +['orange', 2], +['meat', 4] ]); // now prices = { banana: 1, orange: 2, meat: 4 } @@ -200,55 +200,55 @@ let prices = Object.fromEntries([ alert(prices.orange); // 2 ``` -We can use `Object.fromEntries` to get a plain object from `Map`. +Ми можемо використати `Object.fromEntries`, щоб отримати звичайний об’єкт з `Map`. -E.g. we store the data in a `Map`, but we need to pass it to a 3rd-party code that expects a plain object. +Наприклад, ми маємо дані в `Map`, але потрібно їх передати в сторонній код, який чекає простий об’єкт. -Here we go: +Ось як це зробити: -```js run +```js run let map = new Map(); map.set('banana', 1); map.set('orange', 2); map.set('meat', 4); *!* -let obj = Object.fromEntries(map.entries()); // make a plain object (*) +let obj = Object.fromEntries(map.entries()); // робимо простий об’єкт (*) */!* -// done! +// Готово! // obj = { banana: 1, orange: 2, meat: 4 } alert(obj.orange); // 2 ``` -A call to `map.entries()` returns an iterable of key/value pairs, exactly in the right format for `Object.fromEntries`. +Виклик `map.entries()` повертає масив пар ключ/значення, як раз в потрібному форматі для `Object.fromEntries`. -We could also make line `(*)` shorter: +Ми могли б написати рядок `(*)` ще коротше: ```js -let obj = Object.fromEntries(map); // omit .entries() +let obj = Object.fromEntries(map); // прибрати .entries() ``` -That's the same, because `Object.fromEntries` expects an iterable object as the argument. Not necessarily an array. And the standard iteration for `map` returns same key/value pairs as `map.entries()`. So we get a plain object with same key/values as the `map`. +Це те ж саме, оскільки `Object.fromEntries` чекає аргументом об’єкт-ітератор, не обов’язково масив. А перебір `map` якраз повертає пари ключ/значення, як і `map.entries()`. Так що в підсумку ми матимемо звичайний об’єкт з тими ж ключами/значеннями, що і в `map`. ## Set -A `Set` is a special type collection - "set of values" (without keys), where each value may occur only once. +Об’єкт `Set` -- це особливий тип колекції: "множина" значень (без ключів), де кожне значення може з’являтися тільки раз. -Its main methods are: +Основні методи: -- `new Set(iterable)` -- creates the set, and if an `iterable` object is provided (usually an array), copies values from it into the set. -- `set.add(value)` -- adds a value, returns the set itself. -- `set.delete(value)` -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. -- `set.has(value)` -- returns `true` if the value exists in the set, otherwise `false`. -- `set.clear()` -- removes everything from the set. -- `set.size` -- is the elements count. +- `new Set(iterable)` -- створює `Set`, якщо аргументом виступає об’єкт-ітератор, тоді значення копіюються в `Set`. +- `set.add(value)` -- додає нове значення до `Set`, повертає `Set`. +- `set.delete(value)` -- видаляє значення з `Set`, повертає `true`, якщо `value` наявне в множині значень на момент виклику методу, інакше `false`. +- `set.has(value)` -- повертає `true`, якщо `value` присутнє в множині `Set`, інакше `false`. +- `set.clear()` -- видаляє всі значення множини `Set`. +- `set.size` -- повертає кількість елементів в множині. -The main feature is that repeated calls of `set.add(value)` with the same value don't do anything. That's the reason why each value appears in a `Set` only once. +Родзинкою `Set` є виклики `set.add(value)`, що повторюються з однаковими значеннями `value`. Повторні виклики цього методу не змінюють `Set`. Це причина того, що кожне значення з’являється тільки один раз. -For example, we have visitors coming, and we'd like to remember everyone. But repeated visits should not lead to duplicates. A visitor must be "counted" only once. +Наприклад, ми очікуємо гостей, і нам необхідно скласти їх список. Але повторні записи не повинні призводити до дублікатів. Кожен гість повинен з’явитися в списку лише один раз. -`Set` is just the right thing for that: +Множина `Set` -- це саме те, що потрібно для цього: ```js run let set = new Set(); @@ -257,76 +257,76 @@ let john = { name: "John" }; let pete = { name: "Pete" }; let mary = { name: "Mary" }; -// visits, some users come multiple times +// підраховуємо гостей, деякі приходять кілька разів set.add(john); set.add(pete); set.add(mary); set.add(john); set.add(mary); -// set keeps only unique values +// set зберігає тільки 3 унікальних значення alert( set.size ); // 3 for (let user of set) { - alert(user.name); // John (then Pete and Mary) + alert(user.name); // John (тоді Pete і Mary) } ``` -The alternative to `Set` could be an array of users, and the code to check for duplicates on every insertion using [arr.find](mdn:js/Array/find). But the performance would be much worse, because this method walks through the whole array checking every element. `Set` is much better optimized internally for uniqueness checks. +Альтернативою множини `Set` може виступати масив для зберігання гостей і додатковий код для перевірки вже наявного елемента за допомогою [arr.find](mdn:js/Array/find). Але в цьому випадку буде гірша продуктивність, тому що `arr.find` проходить весь масив для перевірки наявності елемента. Множина `Set` краще оптимізована для перевірки унікальності. -## Iteration over Set +## Перебір об’єкта Set -We can loop over a set either with `for..of` or using `forEach`: +Ми можемо перебрати вміст об’єкта `set` як за допомогою методу `for..of`, так і використовуючи `forEach`: ```js run let set = new Set(["oranges", "apples", "bananas"]); for (let value of set) alert(value); -// the same with forEach: +// те ж саме з forEach: set.forEach((value, valueAgain, set) => { alert(value); }); ``` -Note the funny thing. The callback function passed in `forEach` has 3 arguments: a `value`, then *the same value* `valueAgain`, and then the target object. Indeed, the same value appears in the arguments twice. +Зауважимо цікаву річ. Функція в `forEach` у `Set` має 3 аргументи: значення 'value', потім знову *те ж саме значення* 'valueAgain', і тільки потім цільовий об’єкт. Це дійсно так, значення з’являється в списку аргументів двічі. -That's for compatibility with `Map` where the callback passed `forEach` has three arguments. Looks a bit strange, for sure. But may help to replace `Map` with `Set` in certain cases with ease, and vice versa. +Це зроблено для сумісності з об’єктом `Map`, в якому колбек `forEach` має 3 аргумента. Виглядає трохи дивно, але в деяких випадках може допомогти легко замінити `Map` на `Set` і навпаки. -The same methods `Map` has for iterators are also supported: +`Set` має ті ж вбудовані методи, що і `Map`: -- `set.keys()` -- returns an iterable object for values, -- `set.values()` -- same as `set.keys()`, for compatibility with `Map`, -- `set.entries()` -- returns an iterable object for entries `[value, value]`, exists for compatibility with `Map`. +- `set.keys()` -- повертає об’єкт-ітератор для значень, +- `set.values()` -- те ж саме, що `set.keys()`, для сумісності з `Map`, +- `set.entries()` -- повертає об’єкт-ітератор для пар виду `[значення, значення]`, присутній для сумісності з `Map`. -## Summary +## Підсумки -`Map` -- is a collection of keyed values. +`Map` -- це колекція ключ/значення. -Methods and properties: +Методи та властивості: -- `new Map([iterable])` -- creates the map, with optional `iterable` (e.g. array) of `[key,value]` pairs for initialization. -- `map.set(key, value)` -- stores the value by the key, returns the map itself. -- `map.get(key)` -- returns the value by the key, `undefined` if `key` doesn't exist in map. -- `map.has(key)` -- returns `true` if the `key` exists, `false` otherwise. -- `map.delete(key)` -- removes the value by the key, returns `true` if `key` existed at the moment of the call, otherwise `false`. -- `map.clear()` -- removes everything from the map. -- `map.size` -- returns the current element count. +- `new Map([iterable])` -- створює колекцію, можна вказати `об’єкт-ітератор` (зазвичай масив) з пар `[ключ, значення]` для ініціалізації. + - `map.set(key, value)` -- записує по ключу `key` значення `value`. +- `map.get(key)` -- повертає значення по `key` або `undefined`, якщо ключ `key` відсутній. +- `map.has(key)` -- повертає `true`, якщо ключ `key` присутній в колекції, інакше `false`. +- `map.delete(key)` -- видаляє елемент по ключу `key`. Повертає `true`, якщо `key` існує на момент виклику функції, інакше `false`. +- `map.clear()` -- очищає колекцію від всіх елементів. +- `map.size` -- повертає поточну кількість елементів. -The differences from a regular `Object`: +Відмінності від звичайного об’єкта `Object`: -- Any keys, objects can be keys. -- Additional convenient methods, the `size` property. +- Що завгодно може бути ключем, в тому числі і об’єкти. +- Є додаткові методи, властивість `size`. -`Set` -- is a collection of unique values. +`Set` -- колекція унікальних значень, так звана «множина». -Methods and properties: +Методи та властивості: -- `new Set([iterable])` -- creates the set, with optional `iterable` (e.g. array) of values for initialization. -- `set.add(value)` -- adds a value (does nothing if `value` exists), returns the set itself. -- `set.delete(value)` -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. -- `set.has(value)` -- returns `true` if the value exists in the set, otherwise `false`. -- `set.clear()` -- removes everything from the set. -- `set.size` -- is the elements count. +- `new Set([iterable])` -- створює `Set`, можна вказати `об’єкт-ітератор` (зазвичай масив). +- `set.add(value)` -- додає значення (якщо воно вже є, то нічого не робить), повертає той же об’єкт `set`. +- `set.delete(value)` -- видаляє значення, повертає `true` якщо `value` було в множині на момент виклику, інакше `false`. +- `set.has(value)` -- повертає `true`, якщо значення присутній в множині, інакше `false`. +- `set.clear()` -- видаляє всі наявні значення. +- `set.size` -- повертає кількість елементів у множині. -Iteration over `Map` and `Set` is always in the insertion order, so we can't say that these collections are unordered, but we can't reorder elements or directly get an element by its number. +Перебір `Map` і `Set` завжди здійснюється в порядку додавання елементів, так що не можна сказати, що це невпорядковані колекції, але поміняти порядок елементів або отримати елемент безпосередньо по його номеру не можна.