Як працювати з foreach




Як працювати з foreach



.for Each ( )

Скільки способами можна обійти масив? Це ще один метод, але без явного опису циклу.

Час читання: менше 5 хв

Оновлено 10 квітня 2024

Коротко

Скопіювати посилання "Коротко" Скопійовано

Метод масиву for Each ( ) дозволяє застосувати колбек-функцію до всіх елементів масиву. Можна використовувати замість класичного циклу for. На відміну від нього for Each ( ) виглядає більш читабельним та зрозумілим.

приклад

Скопіювати посилання "Приклад" Скопійовано

const numbers = [1, 2, 3, 4]
numbers.forEach((num) =>  const square = num * num
console.log('Квадрат числа дорівнює:' + square)>)
const numbers =
[1,
2,
3,
4] numbers.forEach((num)
=>

const square = num * num console.log('Квадрат числа дорівнює: '
+ square)
>)




Квадрат числа дорівнює: 1 Квадрат числа дорівнює: 4 Квадрат числа дорівнює: 9 Квадрат числа дорівнює: 16

Цілком цікаві можуть зазирнути у вихідники, щоб подивитися як for Each ( ) активно використовується в коді цього прикладу.

Як пишеться

Скопіювати посилання "Як пишеться" Скопійовано

Для того, щоб використовувати for Each ( ) , знадобиться колбек-функція, яку необхідно передавати в метод. Функцію можна оголосити заздалегідь:

function sliceFruit(fruit)  console.log('Розрізаю' + fruit + '!')>
const fruits = ['🍎', '🍊', '🍋', '🍓', '🥝']
fruits.forEach(sliceFruit)
function
sliceFruit(fruit)

console.log('Розрізаю'
+ fruit +
'!')
>
const fruits =
['🍎',
'🍊',
'🍋',
'🍓',
'🥝'] fruits.forEach(sliceFruit)




Або створити її прямо у місці виклику:

const food = ['🍔', '🍟', '🍦']
food.forEach((item) =>  console.log('Мам, купи' + item + '!')>)
const food =
['🍔',
'🍟',
'🍦'] food.forEach((item)
=>

console.log('Мам, купи'
+ item +
'!')
>)




Важливо знати, які параметри набуває колбек. Усього їх три:

  • item - елемент масиву у поточній ітерації;
  • index - індекс поточного елемента;
  • arr - сам масив, який ми перебираємо.

Повернемося, наприклад, з їжею:

const food = ['🍔', '🍟', '🍦']
food.forEach((item, index, arr) =>  console.log('Поточний елемент' + item)
console.log('Його індекс' + index)
console.log('Початковий масив' + arr)>)
const food =
['🍔',
'🍟',
'🍦'] food.forEach((item, index, arr)
=>

console.log('Поточний елемент'
+ item)
console.log('Його індекс'
+ index)
console.log('Початковий масив'
+ arr)
>)




Поточний елемент 🍔 Його індекс 0 Початковий масив ['🍔', '🍟', '🍦'] Поточний елемент 🍟 Його індекс 1 Вихідний масив ['🍔', '🍟', '🍦'] Поточний елемент 🍦 Його індекс 2 ['🍔', '🍟', '🍦']

Оскільки forEach віддає колбеку три параметри, якщо не вказати іншого, можна просто передати (а не викликати) колбек без вказівки параметрів, щоб forEach віддав всі три параметри і колбек прийняв і обробив їх усі.

food.forEach(
console.log)
food.forEach(
console.log
)





…виведе і значення елемента, та його індекс, і весь масив:

Як зрозуміти

Скопіювати посилання "Як зрозуміти" Скопійовано

Метод for Each ( ) можна використовувати, коли вам необхідно здійснити ту саму операцію над усіма елементами масиву.

Хоча в JavaScript вже є можливість робити це, використовуючи цикл for , метод for Each ( ) - це відмінна альтернатива з рядом переваг:

  • Використання методу for Each ( ) декларативним способом визначити нашу операцію. З погляду читабельності коду це більше наближено до природної мови та лаконічно.
  • Дозволяє зручно отримувати елемент у поточній ітерації, без необхідності щоразу звертатися до масиву за індексом.

Проте водночас ми отримуємо й кілька недоліків:

  • У for Each ( ) не працюватимуть return , break і continue , а отже, ніяк не можемо перервати або пропустити ітерацію. Тому, якщо для вирішення завдання необхідно скористатися будь-яким із цих операторів, доведеться використовувати звичайний цикл for .
  • for Each ( ) обробляє елементи масиву прямому порядку, тобто ми можемо пройти масивом з кінця.

💡 Метод for Each ( ) автоматично вбудований у будь-який масив.

const empty = []const someNums = [1, 2, 3]
console.log(empty.forEach)// Виведе функцію
console.log(someNums.forEach)// І тут теж
const obj = <>
console.log(obj.forEach)// undefined, тому що об'єкти не мають такого методу
const empty =
[]
const someNums =
[1,
2,
3]
console.log(empty.forEach)
// Виведе функцію
console.log(someNums.forEach)
// І тут теж
const obj =
>
console.log(obj.forEach)
// undefined, тому що об'єкти не мають такого методу




На практиці

Скопіювати посилання "На практиці" Скопійовано

Єгор Огарков радить

Скопіювати посилання "Егор Огарков радить" Скопійовано

🛠 Імена аргументів у функції-колбеку можна давати будь-які, головне, щоб код було зручно читати.

🛠 Три параметри у функції-колбеку дозволяють проводити додаткові перевірки. Наприклад, чи це останній елемент масиву:

const nums = [1, 2, 3, 4, 5]
nums.forEach((num, index, arr) =>  // Додамо до першого числа 9
if (index === 0)  num = num + 9
>
// А останнє помножимо на 2
else if (index === arr.length - 1)  num = num * 2
>
console.log(num)>)
const nums =
[1,
2,
3,
4,
5] nums.forEach((num, index, arr)
=>

// Додамо до першого числа 9
if
(index ===
0)
 num = num +
9
>
// А останнє помножимо на 2
else
if
(index === arr.length
-
1)
 num = num *
2
>
console.log(num)
>)




На співбесіді

Скопіювати посилання "На співбесіді" Скопійовано

Поясніть різницю між методами for Each() та map().

Копіювати посилання "Поясніть різницю між методами forEach() та map()." Скопійовано

Скопіювати посилання "Алекс Рассудіхін відповідає" Скопійовано

Методи for Each ( ) і map ( ) визначено кількох структурах даних. Ми розглянемо, чим відрізняються ці методи для масивів.

Обидва методи приймають колбек, що викликається кожному за елемента. Різниця в тому, що метод для Each ( ) нічого не повертає, а метод map ( ) повертає новий масив з результатами виклику колбека на кожному вихідному елементі. Якщо переданий колбек нічого не повертає у новому масиві з'явиться undefined

Ви можете повернути значення з колбека для for Each ( ) але воно ніяк не буде використовуватися далі.

[1,2,3].forEach(a => a + 3);
[1,2,3].forEach(a
=> a +
3);





Використовуючи map ( ), ви можете створювати ланцюжки викликів. Якщо ви будете використовувати for Each ( ) так зробити не вийде.

const myArray = [4, 2, 8, 7, 3, 1, 0];const myArray2 = myArray.map(item => item * 2). sort ((a, b) => a - b);
console.log(myArray); // [4, 2, 8, 7, 3, 1, 0]console.log(myArray2); // [0, 2, 4, 6, 8, 14, 16]
const myArray =
[4,
2,
8,
7,
3,
1,
0];
const myArray2 = myArray.map(item
=> item *
2).sort((a, b)
=> a - b);
console.log(myArray);
// [4, 2, 8, 7, 3, 1, 0]
console.log(myArray2);
// [0, 2, 4, 6, 8, 14, 16]





У прикладі вище змінився лише my Array2.

Для закріплення, реалізуємо ту ж логіку за допомогою for Each ( ) .

const myArray = [4, 2, 8, 7, 3, 1, 0];let myArray2 = [];
myArray.forEach(item =>  myArray2.push(item * 2);>);
myArray2 = myArray2.sort((a, b) => a - b);
console.log(myArray); // [4, 2, 8, 7, 3, 1, 0]console.log(myArray2); // [0, 2, 4, 6, 8, 14, 16]
const myArray =
[4,
2,
8,
7,
3,
1,
0];
let myArray2 =
[]; myArray.forEach(item
=>
 myArray2.push(item *
2);
>); myArray2 = myArray2.sort((a, b)
=> a - b);
console.log(myArray);
// [4, 2, 8, 7, 3, 1, 0]
console.log(myArray2);
// [0, 2, 4, 6, 8, 14, 16]




forEach()

forEach() JavaScript - це метод, що дозволяє перебирати і взаємодіяти з елементами масиву, викликаючи для кожного колбек-функцію.

Синтаксис

arr = [3,2,6,9] arr.forEach(element => < console.log(element) >)

У даному прикладі element це елемент масиву arr , а стрілочна функція виступає як колбек-функції, в результаті отримаємо в console усі цифри.

Як параметри методу також можна вказати індекс і сам масив.

let arr = [3,2,6,9] arr.forEach((element, index, array) => < console.log(element) console.log(index) console.log(array) >)

element - елемент масиву, при виклику функції буде використано як значення this , якщо element пропустити this буде рівно undefined .

index – індекс елемента.

array - масив із яким взаємодіє метод.

Усі параметри необов'язкові, а назви не суворі і їх можна назвати на розсуд.

Функцію можна винести окремо, тоді запис виглядає так.

 let arr = [3,2,6,9] arr.forEach(addToConsole) function addToConsole(element, index, array)

Такий запис теж буде коректним.

let arr = [3,2,6,9] arr.forEach(function addToConsole(element, index, array) < console.log(element) >)

Відмінність forEach() від циклу for

Для того, щоб взаємодіяти з елементами масиву підійде, як метод forEach() , так і цикл for проте серед них є деякі відмінності.

1. forEach() більш лаконічний у записі і вже за умовчанням є вбудованим методом будь-якого масиву.

2. forEach() проігнорує пропущений елемент масиву, for видасть undefined .

3. У forEach() не працюватимуть директиви переривання break і continue , for навпаки.

4. forEach() взаємодіє з елементами масиву строго по порядку, у свою чергу використовуючи for , наприклад, можна обійти елементи у зворотному порядку.

Особливості роботи forEach()

1. Елементи, які повинні обійти forEach() визначаються до першого виклику функції, все, що буде додано після метод не обійде.

2. Якщо елемент масиву буде змінено в процесі роботи forEach() , то в callback функцію потрапить те значення, яке матиме елемент на момент обходу.

3. Елемент віддалений до обходу, врахований не буде.

4. У forEach() колбек-функція не буде викликана для пропущених елементів, але спрацює для порожніх, рівних undefined або NaN .

Посібник з Java 8 forEach

У цьому посібнику ми побачимо, як використовувати forEach з колекціями, який аргумент він приймає і чим цей цикл відрізняється від розширеного циклу for .

Якщо вам потрібно освіжити деякі концепції Java 8, наша добірка статей допоможе.

2. Основи forEach

У Java інтерфейс Collection має Iterable як суперінтерфейс. І цей інтерфейс має новий API, починаючи з Java 8:


void
forEach(Consumer?
super
T>
action)

Простіше кажучи, в Javadoc forEach говориться, що він «виконує задану дію для кожного елемента Iterable доти, доки всі елементи не будуть оброблені або поки дія не викличе виняток».

Отже, за допомогою forEach ми можемо перебирати колекцію та виконувати задану дію над кожним елементом, як і будь-який інший Iterator.

Наприклад, розглянемо версію циклу для ітерації та друку колекції рядків : ``


for
(String
name
:
names)



System.out.println(name);


>

Ми можемо написати це, використовуючи forEach :


names.forEach(name
->



System.out.println(name);


>);

3. Використання методу forEach

Ми використовуємо forEach для перебору колекції та виконання певної дії над кожним елементом. Дія, що виконується міститься в класі, що реалізує інтерфейс Consumer , і передається forEach як аргумент.

Інтерфейс Consumer – це функціональний інтерфейс (інтерфейс з одним абстрактним методом). Він приймає введення та не повертає жодного результату.


@FunctionalInterface


public
interface
Consumer



void
accept(T
t);


>

Тому будь-яка реалізація, наприклад, споживач, який просто друкує String :


ConsumerString>
printConsumer
=
new
ConsumerString>()



public
void
accept(String
name)



System.out.println(name);


>;


>;

можна передати forEach як аргумент:


names.forEach(printConsumer);

Але це не єдиний спосіб створити дію через споживача і використовувати forEach API.

Давайте розглянемо три найбільш популярні способи використання методу forEach.

3.1. Реалізація анонімного споживача

Ми можемо створити екземпляр реалізації інтерфейсу Consumer , використовуючи анонімний клас, а потім застосувати його як аргумент до методу forEach :


ConsumerString>
printConsumer=
new
ConsumerString>()



public
void
accept(String
name)



System.out.println(name);


>


>;

names.forEach(printConsumer);

Це добре працює. Але якщо ми проаналізуємо приклад, побачимо, що корисна частина — це насправді код усередині методу accept() .

Хоча лямбда-вирази тепер є нормою і більш простим способом зробити це, все ж таки варто знати, як реалізувати інтерфейс Consumer .

3.2. Лямбда-вираз

Основна перевага функціональних інтерфейсів Java 8 полягає в тому, що ми можемо використовувати лямбда-вирази для їх створення та уникнути використання громіздких реалізацій анонімних класів.

Оскільки Consumer Interface це функціональний інтерфейс, ми можемо висловити його в Lambda:

Тому наш printConsumer спрощений:


name
->
System.out.println(name)

І ми можемо передати його forEach :


names.forEach(name
->
System.out.println(name));

З моменту появи лямбда-виражень у Java 8 це, ймовірно, найпоширеніший спосіб використання методу forEach.

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

3.3. Довідник за методом

Ми можемо використовувати синтаксис посилання на метод замість звичайного синтаксису Lambda, де вже існує метод виконання операції над класом:


names.forEach(System.out::println);

4. Робота з forEach

4.1. Ітерація з колекції

Будь-яка ітерація типу Collection - список, набір, черга і т.д. - має той же синтаксис для використання дляEach.

Тому, як ми бачили, ми можемо перебирати елементи списку так:


ListString>
names
=
Arrays.asList("Larry",
"Steve",
"James");


names.forEach(System.out::println);

SetString>
uniqueNames
=
new
HashSet>(Arrays.asList("Larry",
"Steve",
"James"));


uniqueNames.forEach(System.out::println);

Нарешті, давайте подивимося на Queue, яка також є Collection:


QueueString>
namesQueue
=
new
ArrayDeque>(Arrays.asList("Larry",
"Steve",
"James"));


namesQueue.forEach(System.out::println);

4.2. Ітерація по карті з використанням картки forEach

Карти не є Iterable, але вони надають власний варіант forEach , який приймає BiConsumer .

Java 8 представляє BiConsumer замість Consumer в forEach Iterable, так що дія може бути виконана одночасно як з ключем, так і зі значенням Map.

Давайте створимо карту із цими записами:


MapInteger,
String>
namesMap
=
new
HashMap>();

namesMap.put(1,
"Larry");

namesMap.put(2,
"Steve");

namesMap.put(3,
"James");

Далі, давайте пройдемося по nameMap , використовуючи forEach Map :


namesMap.forEach((key,
value)
->
System.out.println(key
+
" "
+
value));

Як бачимо тут, ми використовували BiConsumer для перебору записів Map :


(key,
value)
->
System.out.println(key
+
" "
+
value)

4.3. Ітерація по карті шляхом ітерації entrySet

Ми також можемо повторювати карту EntrySet , використовуючи дляEach Iterable . ``

Оскільки записи картки зберігаються в наборі з ім'ям EntrySet, ми можемо повторити це, використовуючи forEach :


namesMap.entrySet().forEach(entry
->
System.out.println(


entry.getKey()
+
" "
+
entry.getValue()));

5. Foreach проти For-Loop

З простої точки зору, обидва цикли забезпечують однакову функціональність: цикл елементів у колекції.

Основне різницю між ними у цьому, що це різні ітератори. Удосконалений цикл for — це зовнішній ітератор, а новий метод forEach — внутрішній.

5.1. Внутрішній ітератор - forEach

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

Натомість ітератор управляє ітерацією і забезпечує обробку елементів один за одним.

Давайте подивимося на приклад внутрішнього ітератора:


names.forEach(name
->
System.out.println(name));

У наведеному вище методі forEach ми бачимо, що наданий аргумент є лямбда-виразом. Це означає, що метод повинен знати тільки те, що має бути зроблено , і вся робота з ітерації буде виконуватись усередині.

5.2. Зовнішній ітератор - цикл for

Зовнішні ітератори змішують те, що і як має виконувати цикл.

Переліки , ітератори і розширений цикл for — це зовнішні ітератори (пам'ятаєте методи iterator() , next() чи hasNext() ?). У всіх цих ітераторах наше завдання – вказати, як виконувати ітерації.

Розглянемо цей знайомий цикл:


for
(String
name
:
names)



System.out.println(name);


>

Хоча ми явно не викликаємо методів hasNext() або next() під час ітерації за списком, базовий код, який забезпечує роботу цієї ітерації, використовує ці методи. Звідси випливає, що складність цих операцій прихована від програміста, але вона все ж таки існує.

На відміну від внутрішнього ітератора, в якому колекція сама виконує ітерацію, нам потрібен зовнішній код, який витягує кожен елемент з колекції.

6. Висновок

У цій статті ми показали, що цикл forEach більш зручний, ніж звичайний цикл for-loop .

Ми також побачили, як працює метод forEach і яку реалізацію можна отримати як аргумент, щоб виконати дію над кожним елементом у колекції.

Нарешті, всі фрагменти, що використовуються в цій статті, доступні в нашій репозиторії GitHub.

  • 1. Огляд
  • 2. Основи forEach
  • 3. Використання методу forEach
    • 3.1. Реалізація анонімного споживача
    • 3.2. Лямбда-вираз
    • 3.3. Довідник за методом
    • 4.1. Ітерація з колекції
    • 4.2. Ітерація по карті з використанням картки forEach
    • 4.3. Ітерація по карті шляхом ітерації entrySet
    • 5.1. Внутрішній ітератор - forEach
    • 5.2. Зовнішній ітератор - цикл for

Схожі статті

  • Ким можна влаштуватися працювати в Америці
  • Як працювати балериною
  • Чи можна працювати мотористом із дипломом механіка
  • Чи перестає тимус працювати з віком
  • Перестав працювати масляний обігрівач
  • Чому не можна працювати навпроти вікна
  • Коли починає працювати гербіцид
  • Чи можна у канві працювати безкоштовно
  • Недавні статті

  • Як бродить зернова брага
  • Що робити якщо не засмагаєш на сонці чому засмага погано лягає на шкіру або перестає прилипати
  • Як швидко зняти гель лак без апарату
  • Як робиться Каті голови
  • Яка гребінець краще для об'єму
  • Чим роблять м'яку покрівлю
  • Чи можна залишати крем для обличчя на ніч
  • Де знаходиться датчик селектора
  • географія нашої діяльності
    вулиця Драгоманова, 27
    вул. Курчатова 1Б
    вул. Міцкевича 130
    вул. Лабунського, 1
    вул. Макарова-Пржевальського
    вул. Толстого 10
    вул. Грушевського 28
    вул. Перший промінь (Черняхівського)
    напишіть нам

    сообщение успешно отправлено
    x