Найти индекс в цикле 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; }
17413 / 12809 / 3355
Регистрация: 17.09.2011
Сообщений: 21,087
Lcvb x, чем ваш ответ отличается от вот этого, данного более 8-и лет назад?
11809 / 8130 / 1241
Регистрация: 21.01.2016
Сообщений: 30,605
kolorotur, да, он не соберётся потому, что Lcvb x не отличает строки от целых знаковых.
15238 / 10356 / 2721
Регистрация: 21.04.2018
Сообщений: 30,670
Записей в блоге: 2
Сообщение от Lcvb x
string CurrentIndex = 0;
17413 / 12809 / 3355
Регистрация: 17.09.2011
Сообщений: 21,087
Usaga, хых, не заметил что там строка.
Это все в корне меняет.
15238 / 10356 / 2721
Регистрация: 21.04.2018
Сообщений: 30,670
Записей в блоге: 2
Сообщение от kolorotur
Это все в корне меняет.
Новое решение старой задачи!
Регистрация: 17.11.2021
Сообщений: 60
Элд Хасп, А что не так ? я создал счетчик который определяет какой индекс читается
11809 / 8130 / 1241
Регистрация: 21.01.2016
Сообщений: 30,605
Lcvb x, попробуйте свой код скомпилировать.
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 и возникла проблема. У меня в приложении элементы.