Как в цикле foreach получить индекс текущего элемента массива
Перейти к содержимому

Как в цикле foreach получить индекс текущего элемента массива

  • автор:

Найти индекс в цикле foreach в PHP

В этой статье показано, как найти индекс в foreach цикл в PHP.

1. Использование ассоциативных массивов

Ассоциативный массив связывает значения с ключами и состоит из любого числа разделенных запятыми key => value пары. Вы можете получить доступ к парам ключ-значение, представленным в ассоциативном массиве, используя следующие foreach синтаксис: он проходит по итерации, на которую указывает $array , и на каждой итерации он присваивает ключ и значение текущего элемента $key а также $value переменные соответственно.

foreach ($array as $key => $value)
statement

Однако это дает текущий элемент ассоциативного массива, а не индекс текущей итерации foreach петля. Идея состоит в том, чтобы поддерживать явный счетчик, начиная с 0 , который увеличивается на каждой итерации цикла.

Получить индекс элемента в foreach цикле

Если «очень хочется», то при условии уникальности элементов массива можно воспользоваться поиском элемента в массиве. Однако этот подход получается всецело хуже обычного for-а:

  • работает за O(n^2), что при большом количестве элементов может создать проблемы с производительностью
  • требует уникальности элементов массива
  • код получается больше и сложнее

Так что этот подход можно рассматривать только для полноты картины:

List list = Arrays.asList(array); for (String str : array)

Вместо метода List.indexOf можно воспользоваться методом ArrayUtils.indexOf из библиотеки Apache Commons Lang, но суть от этого не меняется — только кода становится чуть меньше

Можно ещё использовать дополнительную переменную:

int index = 0; for (String str : array)

но это уже получается почти что обычный for

Array.prototype.forEach()

Метод forEach() выполняет указанную функцию один раз для каждого элемента в массиве.

Интерактивный пример

Синтаксис

arr.forEach(function callback(currentValue, index, array) < //your iterator >[, thisArg]);

Параметры

Функция, которая будет вызвана для каждого элемента массива. Она принимает от одного до трёх аргументов:

Текущий обрабатываемый элемент в массиве.

Индекс текущего обрабатываемого элемента в массиве.

Массив, по которому осуществляется проход.

Необязательный параметр. Значение, используемое в качестве this при вызове функции callback .

Возвращаемое значение

Описание

Метод forEach() выполняет функцию callback один раз для каждого элемента, находящегося в массиве в порядке возрастания. Она не будет вызвана для удалённых или пропущенных элементов массива. Однако, она будет вызвана для элементов, которые присутствуют в массиве и имеют значение undefined .

Функция callback будет вызвана с тремя аргументами:

  • значение элемента (value)
  • индекс элемента (index)
  • массив, по которому осуществляется проход (array)

Если в метод forEach() был передан параметр thisArg , при вызове callback он будет использоваться в качестве значения this . В противном случае, в качестве значения this будет использоваться значение undefined . В конечном итоге, значение this , наблюдаемое из функции callback , определяется согласно обычным правилам определения this , видимого из функции .

Диапазон элементов, обрабатываемых методом forEach() , устанавливается до первого вызова функции callback . Элементы, добавленные в массив после начала выполнения метода forEach() , не будут посещены функцией callback . Если существующие элементы массива изменятся, значения, переданные в функцию callback , будут значениями на тот момент времени, когда метод forEach() посетит их; удалённые элементы посещены не будут. Если уже посещённые элементы удаляются во время итерации (например, с помощью shift() ), последующие элементы будут пропущены. ( Смотри пример ниже )

Примечание: Не существует способа остановить или прервать цикл forEach() кроме как выбрасыванием исключения. Если вам необходимо такое поведение, метод forEach() неправильный выбор.

Досрочное прекращение может быть достигнуто с:

  • Простой цикл for
  • Циклы for. of / for. in
  • Array.prototype.every()
  • Array.prototype.some()
  • Array.prototype.find()
  • Array.prototype.findIndex()

Если нужно протестировать элементы массива на условие и нужно вернуть булево значение, вы можете воспользоваться методами every() , some() , find() или findIndex() .

Метод forEach() выполняет функцию callback один раз для каждого элемента массива; в отличие от методов every() и some() , он всегда возвращает значение undefined .

Примеры

Нет операции для неинициализированных значений (разреженные массивы)

const arraySparse = [1, 3, , 7]; let numCallbackRuns = 0; arraySparse.forEach((element) =>  console.log(element); numCallbackRuns++; >); console.log("numCallbackRuns: ", numCallbackRuns); // 1 // 3 // 7 // numCallbackRuns: 3 // комментарий: как вы видите пропущенное значение между 3 и 7 не вызывало функцию callback. 

Конвертируем цикл for в forEach

const items = ["item1", "item2", "item3"]; const copy = []; // до for (let i = 0; i  items.length; i++)  copy.push(items[i]); > // после items.forEach(function (item)  copy.push(item); >); 

Печать содержимого массива

Примечание: Для отображения содержимого массива в консоли вы можете использовать console.table() , который выводит отформатированную версию массива.

Следующий пример иллюстрирует альтернативный подход, использующий forEach() .

Следующий код выводит каждый элемент массива на новой строке журнала:

function logArrayElements(element, index, array)  console.log("a[" + index + "] token operator">+ element); > // Обратите внимание на пропуск по индексу 2, там нет элемента, поэтому он не посещается [2, 5, , 9].forEach(logArrayElements); // логи: // a[0] = 2 // a[1] = 5 // a[3] = 9 

Использование thisArg

Следующий (надуманный) пример обновляет свойства объекта, когда перебирает записи массива:

function Counter()  this.sum = 0; this.count = 0; > Counter.prototype.add = function (array)  array.forEach((entry) =>  this.sum += entry; ++this.count; >, this); // ^---- Note >; const obj = new Counter(); obj.add([2, 5, 9]); obj.count; // 3 obj.sum; // 16 

Поскольку в forEach() передан параметр thisArg ( this ), он затем передаётся в callback при каждом вызове. И callback использует его в качестве собственного значения this .

Примечание: Если при передаче callback функции используется выражение стрелочной функции , параметр thisArg может быть опущен, так как все стрелочные функции лексически привязываются к значению this .

Прерывание цикла

Следующий код использует Array.prototype.every() для логирования содержимого массива и останавливается при превышении значением заданного порогового значения THRESHOLD .

var THRESHOLD = 12; var v = [5, 2, 16, 4, 3, 18, 20]; var res; res = v.every(function (element, index, array)  console.log("element:", element); if (element >= THRESHOLD)  return false; > return true; >); console.log("res:", res); // логи: // element: 5 // element: 2 // element: 16 // res: false res = v.some(function (element, index, array)  console.log("element:", element); if (element >= THRESHOLD)  return true; > return false; >); console.log("res:", res); // логи: // element: 5 // element: 2 // element: 16 // res: true 

Функция копирования объекта

Следующий код создаёт копию переданного объекта. Существует несколько способов создания копии объекта, и это один из них. Он позволяет понять, каким образом работает Array.prototype.forEach() , используя функции мета-свойств Object.* из ECMAScript 5.

function copy(o)  var copy = Object.create(Object.getPrototypeOf(o)); var propNames = Object.getOwnPropertyNames(o); propNames.forEach(function (name)  var desc = Object.getOwnPropertyDescriptor(o, name); Object.defineProperty(copy, name, desc); >); return copy; > var o1 =  a: 1, b: 2 >; var o2 = copy(o1); // теперь o2 выглядит также, как и o1 

Модификация массива во время итерации

В следующем примере в лог выводится «one» , «two» , «four» .

При достижении записи, содержащей значение ‘two’ , первая запись всего массива удаляется, в результате чего все оставшиеся записи перемещаются на одну позицию вверх. Поскольку элемент ‘four’ теперь находится на более ранней позиции в массиве, ‘three’ будет пропущен.

forEach() не делает копию массива перед итерацией.

let words = ["one", "two", "three", "four"]; words.forEach((word) =>  console.log(word); if (word === "two")  words.shift(); > >); // one // two // four 

Выравнивание (уплощение) массива

Следующий пример приведён только для целей обучения. Если вы хотите выравнять массив с помощью встроенных методов, вы можете использовать Array.prototype.flat()

function flatten(arr)  const result = []; arr.forEach((i) =>  if (Array.isArray(i))  result.push(. flatten(i)); > else  result.push(i); > >); return result; > // Usage const nested = [1, 2, 3, [4, 5, [6, 7], 8, 9]]; flatten(nested); // [1, 2, 3, 4, 5, 6, 7, 8, 9] 

Полифил

Метод forEach() был добавлен к стандарту ECMA-262 в 5-м издании; поэтому он может отсутствовать в других реализациях стандарта. Вы можете работать с ним, добавив следующий код в начало ваших скриптов, он позволяет использовать forEach() в реализациях, которые не поддерживают этот метод. Этот алгоритм является точно тем, что описан в ECMA-262 5-го издания; он предполагает, что Object и TypeError имеют свои первоначальные значения и что callback.call вычисляется в оригинальное значение Function.prototype.call() .

// Шаги алгоритма ECMA-262, 5-е издание, 15.4.4.18 // Ссылка (en): http://es5.github.io/#x15.4.4.18 // Ссылка (ru): http://es5.javascript.ru/x15.4.html#x15.4.4.18 if (!Array.prototype.forEach)  Array.prototype.forEach = function (callback, thisArg)  var T, k; if (this == null)  throw new TypeError(" this is null or not defined"); > // 1. Положим O равным результату вызова ToObject passing the |this| value as the argument. var O = Object(this); // 2. Положим lenValue равным результату вызова внутреннего метода Get объекта O с аргументом "length". // 3. Положим len равным ToUint32(lenValue). var len = O.length >>> 0; // 4. Если IsCallable(callback) равен false, выкинем исключение TypeError. // Смотрите: http://es5.github.com/#x9.11 if (typeof callback !== "function")  throw new TypeError(callback + " is not a function"); > // 5. Если thisArg присутствует, положим T равным thisArg; иначе положим T равным undefined. if (arguments.length > 1)  T = thisArg; > // 6. Положим k равным 0 k = 0; // 7. Пока k < len, будем повторятьwhile (k  len)  var kValue; // a. Положим Pk равным ToString(k). // Это неявное преобразование для левостороннего операнда в операторе in // b. Положим kPresent равным результату вызова внутреннего метода HasProperty объекта O с аргументом Pk. // Этот шаг может быть объединён с шагом c // c. Если kPresent равен true, то if (k in O)  // i. Положим kValue равным результату вызова внутреннего метода Get объекта O с аргументом Pk. kValue = O[k]; // ii. Вызовем внутренний метод Call функции callback с объектом T в качестве значения this и // списком аргументов, содержащим kValue, k и O. callback.call(T, kValue, k, O); > // d. Увеличим k на 1. k++; > // 8. Вернём undefined. >; > 

Спецификации

Specification
ECMAScript Language Specification
# sec-array.prototype.foreach

Совместимость с браузерами

BCD tables only load in the browser

Смотрите также

  • Array.prototype.find()
  • Array.prototype.findIndex()
  • Array.prototype.map()
  • Array.prototype.every()
  • Array.prototype.some()
  • Map.prototype.forEach() (en-US)
  • Set.prototype.forEach()

Foreach как узнать индекс читаемого массива?

Как узнать индекс элемента массива?
Доброго времени суток Подскажите пожалуйста как узнать индекс элемента массива?

Как узнать индекс у элемента массива?
Доброго времени суток. У меня есть массив GameObject`ов public GameObject spawnCells, в которых у.

Как узнать индекс массива нового Элемента управления
Создаем динамически КомбоБоксы, и в подпрограмме события на этот комбобокс пытаюсь узнать индекс.

2136 / 1505 / 565
Регистрация: 05.04.2010
Сообщений: 2,881

1 2 3 4 5 6
int index = 0; foreach (string element in BitMatrixPoverxnost) { // Что-то делаем с index index++; }

Регистрация: 23.01.2012
Сообщений: 449

Да. сейчас у меня это работает именно так.
Но может есть возможность узнать индекс не прибегая к счетчику ?

2136 / 1505 / 565
Регистрация: 05.04.2010
Сообщений: 2,881
@sasha0192, использовать цикл for.
Регистрация: 23.01.2012
Сообщений: 449

Хорошо.
Тогда еще вопросы, а можно ускорить работу foreach ? ну например разбить поток на потоки ?
если да, то как ?

2136 / 1505 / 565
Регистрация: 05.04.2010
Сообщений: 2,881

Добавлено через 1 минуту
Там глядишь и таски изучишь.

6046 / 3455 / 335
Регистрация: 14.06.2009
Сообщений: 8,136
Записей в блоге: 2
никак, разбивать нужно исходные данные на куски и в каждом потоке свой foreach создавать
Регистрация: 17.11.2021
Сообщений: 60

1 2 3 4 5
string CurrentIndex = 0; foreach (string element in BitMatrixPoverxnost) { CurrentIndex += 1; }

Эксперт .NET

17413 / 12809 / 3355
Регистрация: 17.09.2011
Сообщений: 21,087
Lcvb x, чем ваш ответ отличается от вот этого, данного более 8-и лет назад?

Эксперт .NET

11809 / 8130 / 1241
Регистрация: 21.01.2016
Сообщений: 30,605
kolorotur, да, он не соберётся потому, что Lcvb x не отличает строки от целых знаковых.

Эксперт .NET

15238 / 10356 / 2721
Регистрация: 21.04.2018
Сообщений: 30,670
Записей в блоге: 2

ЦитатаСообщение от Lcvb x Посмотреть сообщение

string CurrentIndex = 0;

Эксперт .NET

17413 / 12809 / 3355
Регистрация: 17.09.2011
Сообщений: 21,087
Usaga, хых, не заметил что там строка.
Это все в корне меняет.

Эксперт .NET

15238 / 10356 / 2721
Регистрация: 21.04.2018
Сообщений: 30,670
Записей в блоге: 2

ЦитатаСообщение от kolorotur Посмотреть сообщение

Это все в корне меняет.

Новое решение старой задачи!

Регистрация: 17.11.2021
Сообщений: 60
Элд Хасп, А что не так ? я создал счетчик который определяет какой индекс читается

Эксперт .NET

11809 / 8130 / 1241
Регистрация: 21.01.2016
Сообщений: 30,605
Lcvb x, попробуйте свой код скомпилировать.

Эксперт .NET

15238 / 10356 / 2721
Регистрация: 21.04.2018
Сообщений: 30,670
Записей в блоге: 2

ЦитатаСообщение от Lcvb x Посмотреть сообщение

я создал счетчик который определяет какой индекс читается
Вы же писали здесь.
А как написал выше Usaga, попробуйте написать свой код в Студии.
Регистрация: 17.11.2021
Сообщений: 60
а точно я перепутал int с string
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Как узнать индекс элемента массива, зная итератор на этот элемент?
Вот пример: #include <iostream> #include <vector> #include <algorithm> size_t get_index .

Возможно ли восстановить файлы из не читаемого массива внешнего диска?
Такая-же ситуация. После создания образа диска и сканирования R-Sdudio восстановил 31 ГБ архива.

Узнать индекс максимального элемента второй половины массива
Нам нужно узнать номер максимального элемента второй половины массива t с 20 элементов

Как узнать индекс в QTreeView?
как узнать индекс любой из просматриваемых ячеек в таблице QTreeView?(желательно верхний)Если ни.

Как узнать индекс PopupMenu?
здравствуйте вот столкнулся с такой проблемы. в PopupMenu 16 строк, хачу узнать на какой строке.

Как узнать индекс значения в списке?
Всем здравствуйте. Как узнать индекс значения в списке, если не знаешь где он находится? То-есть.

Как узнать индекс элемента в WrapPanel?
Всем привет, недавно сел писать приложение на WPF и возникла проблема. У меня в приложении элементы.

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

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