php for in array

Цикл for — PHP: Массивы

Работа с массивами практически всегда подразумевает итерацию по его элементам. Самый простой способ выполнить её — циклы.

Обход

В данном коде создаётся массив из трёх элементов — имён. Далее в цикле происходит обход массива и вывод на экран всех имён так, что каждое имя оказывается на новой строке.

Но есть и другой способ. Можно просто идти от верхней границы к нижней. В такой ситуации код меняется на следующий:

Изменение

Сам цикл при изменении остаётся тем же самым, меняется только его тело. Предположим, что перед нами стоит задача нормализации списка электронных адресов. Допустим, в нормализацию адресов входит приведение их к нижнему регистру. Тогда код будет выглядеть так:

Инициализация цикла

Содержимое первого блока инициализации выполняется перед началом цикла и только один раз.

В третьем блоке содержатся выражения, которые обрабатываются в конце итерации цикла. Обычно здесь происходит необходимое преобразование счётчика, например, инкремент.

В процессе работы цикла выражение, которое содержится в блоке условий вычисляется заново. Это значит, что в нашем примере длина массива count($colors) будет вычисляться вновь и вновь при каждом проходе цикла. Так как сам массив остаётся неизменным, то повторное вычисление размера оказывается избыточным. Повторения операции можно избежать, если определить переменную за пределами цикла и присвоить ей необходимое значение.

А вот пример использования нескольких выражений в блоке изменения счётчика:

Источник

Php for in array

You can also use the alternative syntax for the foreach cycle:

I cannot stress this point of the documentation enough! Here is a simple example of exactly why this must be done:

Even though it is not mentioned in this article, you can use «break» control structure to exit from the «foreach» loop.

WARNING: Looping through «values by reference» for «extra performance» is an old myth. It’s actually WORSE!

?>

Which do you think is faster?

Lots of people think the answer is two() because it uses «reference to value, which it doesn’t have to copy each value when it loops».

Well, that’s totally wrong!

Here’s what actually happens:

Alright, so what’s the second version doing? The beloved «iterate values by reference»?

— This function takes an array as argument ($arr).
— The array function argument itself isn’t passed by reference, so the function knows it isn’t allowed to modify the original at all.
— Then the foreach loop happens. The array itself wasn’t passed by reference to the function, so PHP knows that it isn’t allowed to modify the outside array.
— But it also sees that you want to look at all VALUES by reference (&$val), so PHP says «Uh oh, this is dangerous. If we just give them references to the original array’s values, and they assign some new value to their reference, they would destroy the original array which they aren’t allowed to touch!».
— So PHP makes a FULL COPY of the ENTIRE array and ALL VALUES before it starts iterating. YIKES!

Therefore: STOP using the old, mythological «&$val» iteration method! It’s almost always BAD! With worse performance, and risks of bugs and quirks as is demonstrated in the manual.

You can always manually write array assignments explicitly, without references, like this:

Источник

in_array

(PHP 4, PHP 5, PHP 7, PHP 8)

in_array — Проверяет, присутствует ли в массиве значение

Описание

Список параметров

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

Примеры

Пример #1 Пример использования in_array()

Второго совпадения не будет, потому что in_array() регистрозависима, таким образом, программа выведет:

Пример #2 Пример использования in_array() с параметром strict

Результат выполнения данного примера:

Пример #3 Пример использования in_array() с массивом в качестве параметра needle

Результат выполнения данного примера:

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

User Contributed Notes 38 notes

Loose checking returns some crazy, counter-intuitive results when used with certain arrays. It is completely correct behaviour, due to PHP’s leniency on variable types, but in «real-life» is almost useless.

The solution is to use the strict checking option.

// First three make sense, last four do not

If you’re working with very large 2 dimensional arrays (eg 20,000+ elements) it’s much faster to do this.

Remember to only flip it once at the beginning of your code though!

# foo it is found in the array or one of its sub array.

For a case-insensitive in_array(), you can use array_map() to avoid a foreach statement, e.g.:

Determine whether an object field matches needle.

= array( new stdClass (), new stdClass () );
$arr [ 0 ]-> colour = ‘red’ ;
$arr [ 1 ]-> colour = ‘green’ ;
$arr [ 1 ]-> state = ‘enabled’ ;

in_array() may also return NULL if the second argument is NULL and strict types are off.

If the strict mode is on, then this code would end up with the TypeError

In a high-voted example, an array is given that contains, amongst other things, true, false and null, against which various variables are tested using in_array and loose checking.

If you have an array like:
$arr = array(0,1,2,3,4,5);

Add an extra if() to adrian foeder’s comment to make it work properly:

If you found yourself in need of a multidimensional array in_array like function you can use the one below. Works in a fair amount of time

This code will search for a value in a multidimensional array with strings or numbers on keys.

I just struggled for a while with this, although it may be obvious to others.

If you have an array with mixed type content such as:

?>

be sure to use the strict checking when searching for a string in the array, or it will match on the 0 int in that array and give a true for all values of needle that are strings strings.

I found out that in_array will *not* find an associative array within a haystack of associative arrays in strict mode if the keys were not generated in the *same order*:

?>

I had wrongly assumed the order of the items in an associative array were irrelevant, regardless of whether ‘strict’ is TRUE or FALSE: The order is irrelevant *only* if not in strict mode.

I would like to add something to beingmrkenny at gmail dot com comparison post. After debugging a system, i discovered a security issue in our system and his post helped me find the problem.

In my additional testing i found out that not matter what you search for in an array, except for 0 and null, you get true as the result if the array contains true as the value.

Examples as php code :

Such the best practice in our case is to use strict mode. Which was not so obvious.

Kelvin’s case-insensitive in_arrayi is fine if you desire loose typing, but mapping strtolower onto the array will (attempt to) cast all array members to string. If you have an array of mixed types, and you wish to preserve the typing, the following will work:

// Note
// You can’t use wildcards and it does not check variable type
?>

A first idea for a function that checks if a text is in a specific column of an array.
It does not use in_array function because it doesn’t check via columns.
Its a test, could be much better. Do not use it without test.

Beware when using this function to validate user input:

$a = array(‘0’ => ‘Opt 1’, ‘1’ => ‘Opt 2’, ‘2’ => ‘Opt 3’);
$v = ‘sql injection’;
var_dump(in_array($v, array_keys($a)));

This will result : true;

If you need to find if a value in an array is in another array you can use the function:

The top voted notes talked about creating strict comparison function, because in_array is insufficient, because it has very lenient type checking (which is PHP default behaviour).

The thing is, in_array is already sufficient. Because as a good programmer, you should never have an array which contains ; all in one array anyway.

It’s better to fix how you store data and retrieve data from user, rather than fixing in_array() which is not broken.

If you’re creating an array yourself and then using in_array to search it, consider setting the keys of the array and using isset instead since it’s much faster.

Recursive in array using SPL

If array contain at least one true value, in_array() will return true every times if it is not false or null

Be careful to use the strict parameter with truth comparisons of specific strings like «false»:

?>

The above example prints:

False is truthy.
False is not truthy.

This function is for search a needle in a multidimensional haystack:

When using numbers as needle, it gets tricky:

Note this behaviour (3rd statement):

in_array(0, array(42)) = FALSE
in_array(0, array(’42’)) = FALSE
in_array(0, array(‘Foo’)) = TRUE
in_array(‘0’, array(‘Foo’)) = FALSE

Watch out for this:

Yes, it seems that is_array thinks that a random string and 0 are the same thing.
Excuse me, that’s not loose checking, that’s drunken logic.
Or maybe I found a bug?

hope this function may be useful to you, it checks an array recursively (if an array has sub-array-levels) and also the keys, if wanted:

If you have a multidimensional array filled only with Boolean values like me, you need to use ‘strict’, otherwise in_array() will return an unexpected result.

Hope this helps somebody, cause it took me some time to figure this out.

If you search for numbers, in_array will convert any strings in your array to numbers, dropping any letters/characters, forcing a numbers-to-numbers comparison. So if you search for 1234, it will say that ‘1234abcd’ is a match. Example:

Esta función falla con las letras acentuadas y con las eñes. Por tanto, no sirve para los caracteres UTF-8.
El siguiente código falla para na cadena = «María Mañas», no reconoce ni la «í» ni la «ñ»:

// ¿La cadena está vacía?
if (empty ($cadena))
<
$correcto = false;
>
else
<
$nombreOapellido = mb_strtoupper ($cadena, «utf-8»);
$longitudCadena = mb_strlen ($cadena, «utf-8»);

Esta función falla con las letras acentuadas y con las eñes. Por tanto, no sirve para los caracteres UTF-8.
El siguiente código falla para na cadena = «María Mañas», no reconoce ni la «í» ni la «ñ»:

// ¿La cadena está vacía?
if (empty ($cadena))
<
$correcto = false;
>
else
<
$nombreOapellido = mb_strtoupper ($cadena, «utf-8»);
$longitudCadena = mb_strlen ($cadena, «utf-8»);

I needed a version of in_array() that supports wildcards in the haystack. Here it is:

$haystack = array( ‘*krapplack.de’ );
$needle = ‘www.krapplack.de’ ;

var_dump(in_array(‘invalid’, array(0,10,20)));
The above code gives true since the ‘invalid’ is getting converted to 0 and checked against the array(0,10,20)

but var_dump(in_array(‘invalid’, array(10,20))); gives ‘false’ since 0 not there in the array

A function to check an array of values within another array.

Second element ‘123’ of needles was found as first element of haystack, so it return TRUE.

If third parameter is not set to Strict then, the needle is found in haystack eventhought the values are not same. the limit behind the decimal seems to be 6 after which, the haystack and needle match no matter what is behind the 6th.

In PHP array function the in_array() function mainly used to check the item are available or not in array.

1. Non-strict validation
2. Strict validation

1. Non-strict validation:
This method to validate array with some negotiation. And it allow two parameters.

Note: the Example 1, we use only two parameter. Because we can’t mention `false` value. Because In default the in_array() take `false` as a boolean value.

In above example,
Example 1 : The `key1` is not value in the array. This is key of the array. So this scenario the in_array accept the search key as a value of the array.
Example 2: The value `577` is not in the value and key of the array. It is some similar to the value `579`. So this is also accepted.

So this reason this type is called non-strict function.

2. Strict validation
This method to validate array without any negotiation. And it have three parameters. If you only mention two parameter the `in_array()` function take as a non-strict validation.

This is return `true` only the search string is match exactly with the array value with case sensitivity.

Источник

О тонкостях работы foreach в PHP

В недавнем дайджесте интересных ссылок о PHP я обнаружил ссылку на комментарий Никиты Попова на StackOverflow, где он подробно рассказывает о механизме «под капотом» управляющей конструкции foreach.
Поскольку foreach действительно иногда работает более, чем странным образом, я счел полезным сделать перевод этого ответа.

Внимание: этот текст подразумевает наличие базовых знаний о функциональности zval’ов в PHP, в частности вы должны знать что такое refcount и is_ref.
foreach работает с сущностями разных типов: с массивами, с простыми объектами (где перечисляются доступные свойства) и с Traversable-объектами (вернее, объектами, у которых определен внутренний обработчик get_iterator). Здесь мы, в основном, говорим о массивах, но я скажу и об остальных в самом конце.

Прежде чем приступить, пара слов о массивах и их обходе, важная для понимания контекста.

Как работает обход массивов

Массивы в PHP являются упорядоченными хеш-таблицами (элементы хеша объединены в двусвязный список) и foreach обходит массив, следуя указанному порядку.

Таким образом, внешние указатели массива могут быть использованы только когда вы полностью уверены, что при обходе никакого пользовательского кода выполняться не будет. А такой код может оказаться в самом неожиданном месте, типа обработчика ошибок или деструктора. Вот почему в большинстве случаев PHP приходится использовать внутренний указатель вместо внешнего. Если бы это было иначе, PHP мог бы упасть из-за segmentation fault, как только пользователь начнет делать что-нибудь необычное.

Проблема внутреннего указателя в том, что он является частью HashTable. Так что, когда вы изменяете его, HashTable меняется вместе с ним. И коль скоро обращение к массивам в PHP делается по значению (а не по ссылке), вы вынуждены копировать массив, чтобы в цикле обходить его элементы.

Простой пример, показывающий важность копирования (кстати, не такая большая редкость), это вложенная итерация:

Здесь вы хотите чтобы оба цикла были независимым, а не хитро перебрасывались одним указателем.

Итак, мы дошли до foreach.

Обход массива в foreach

Теперь вы знаете, для чего foreach приходится создавать копию массива, прежде чем обойти его. Но это явно не вся история. Сделает PHP копию или нет, зависит от нескольких факторов:

Итак, это первая часть тайны: функция копирования. Вторая часть это то, как текущая итерация выполняется, и она тоже довольно странная. «Обычный» образец итерации, который вы уже знаете (и который часто используется в PHP — отдельно от foreach) выглядит примерно так (псевдокод):

итерация foreach выглядит немного иначе:

Такой режим работы foreach также является причиной, по которой внутренний указатель массива переходит к следующему элементу, если текущий удалён, а не к предыдущему (как вы могли бы ожидать). Всё сделано так, чтобы отлично работать с foreach (но, очевидно, со всем остальным будет работать не так хорошо, пропуская элементы).

Последствия для кода

Первое следствие вышеописанного поведения в том, что foreach копирует итерируемый массив в многих случаях (медленно). Но отриньте страх: я пробовал удалить требование копирования и не смог увидеть ускорения работы нигде, кроме искусственных бенчмарков (в которых итерация происходила в два раза быстрее). Похоже, люди просто не итерируют достаточно много.

Второе следствие в том, что обычно не должно быть других следствий. Поведение foreach, в основном, вполне понятно пользователю и просто работает как следует. Вас не должно волновать, как происходит копирование (и происходит ли оно вообще), и в какой конкретно момент времени перемещается указатель.

И третье следствие — и тут мы как раз подходим к вашим проблемам — в том, что иногда мы видим очень странное поведение, которое трудно понять. Это происходит конкретно тогда, когда вы пытаетесь модифицировать сам массив, который вы обходите в цикле.

Большую коллекцию поведения в пограничных случаях, которые появляются, когда вы модифицируете массив в ходе итерации, можно найти в тестах PHP. Вы можете начать с этого теста, после чего изменять 012 на 013 в адресе, и так далее. Вы увидите, как поведение foreach будет проявляться в разных ситуациях (всякие комбинации ссылок и.т.д.).

А сейчас вернёмся к вашим примерам:

Та же ситуация, что и в первом тесте.

Но эти примеры недостаточно убедительны. Поведение начинает быть по настоящему непредсказуемым, когда вы используете current в цикле:

Теперь попробуем сделать небольшое изменение:

Здесь у нас is_ref=1, так что массив не копирован (так как и выше). Но сейчас когда есть is_ref, массив больше не нужно разделять, передавая по ссылке к current. Теперь current и foreach работают с одним массивом. Вы видите массив сдвинутым на единицу как раз из-за того, как foreach обращается с указателем.

То же самое вы увидите, когда будете делать обход массива по ссылкам:

Еще одна небольшая вариация, здесь мы присвоим наш массив еще одной переменной:

Итерация объектов

При итерации объектов имеет смысл рассмотреть два случая:

Объект не Traversable (вернее, не определен внутренний обработчик get_iterator)

В этом случае итерация происходит почти так же, как у массивов. Та же семантика копирования. Единственное отличие: foreach запустит некий дополнительный код, чтобы пропустить свойства, недоступные в текущей области видимости. Еще пара интересных фактов:

Объект Traversable

В этом случае всё, что сказано выше, не будет применяться никоим образом. Также PHP не будет копировать и не будет применять никакие трюки вроде увеличения указателя до прохода цикла. Я думаю что режим прохода по обходимому (Traversable) объекту куда более предсказуем и не требует дальнейшего описания.

Замена итерируемого объекта во время цикла

Другой необычный случай, который я не упомянул — PHP допускает возможность замены итерируемого объекта во время цикла. Вы можете начать с одним массивом и продолжить, заменив его на полдороге другим. Или начать с массивом, в затем заменить его объектом:

Как видите, PHP просто начал обходить другую сущность, как только произошла замена.

Изменение внутреннего указателя массива во время итерации

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

Тут вы можете получить не то, что ожидали: если вызывать next или prev в теле цикла (в случае передачи по ссылке), вы увидите, что внутренний указатель переместился, но это никак не повлияло на поведение итератора. Причина в том, что foreach делает бекап текущей позиции и хеша текущего элемента в HashPointer после каждого прохода цикла. На следующей проходе foreach проверит, не менялась ли позиция внутреннего указателя и попытается восстановить ее, используя этот хеш.

Давайте посмотрим что означает «попытается». Первый пример показывает, как изменение внутреннего указателя не меняет режим foreach:

Теперь давайте попробуем сделать unset элементу, к которому обратится foreach при первом проходе (ключ 1):

Тут вы увидите, что счетчик сброшен, так как не удалось найти элемент с подходящим хешом.

Имейте в виду, хеш — всего лишь хеш. Случаются коллизии. Попробуем теперь так:

Работает так, как мы и ожидали. Мы удалили ключ EzFY (тот, где как раз был foreach), так что был сделан сброс. Также мы добавили дополнительный ключ, поэтому в конце мы видим 4.

И вот тут приходит неведомое. Что произойдёт, если заменить ключ FYFY с FYFZ? Давайте попробуем:

Сейчас цикл перешёл непосредственно к новому элементу, пропуская всё остальное. Это потому что ключ FYFY имеет коллизию с EzFY (вообще-то, все ключи из этого массива тоже). Более этого, элемент FYFY находится по тому же адресу в памяти, что и элемент EzFY который только что был удален. Так что для PHP это будет та же самая позиция с тем же хешом. Позиция «восстановлена» и происходит переход к концу массива.

Источник

Функции для работы с массивами

Содержание

User Contributed Notes 14 notes

A simple trick that can help you to guess what diff/intersect or sort function does by name.

Example: array_diff_assoc, array_intersect_assoc.

Example: array_diff_key, array_intersect_key.

Example: array_diff, array_intersect.

Example: array_udiff_uassoc, array_uintersect_assoc.

This also works with array sort functions:

Example: arsort, asort.

Example: uksort, ksort.

Example: rsort, krsort.

Example: usort, uasort.

?>
Return:
Array ( [ 0 ] => Cero [ 1 ] => Uno [ 2 ] => Dos [ 3 ] => Cuatro [ 4 ] => Cinco [ 5 ] => Tres [ 6 ] => Seis [ 7 ] => Siete [ 8 ] => Ocho [ 9 ] => Nueve [ 10 ] => Diez )
Array ( [ 0 ] => Cero [ 1 ] => Uno [ 2 ] => Dos [ 3 ] => Tres [ 4 ] => Cuatro [ 5 ] => Cinco [ 6 ] => Seis [ 7 ] => Siete [ 8 ] => Ocho [ 9 ] => Nueve [ 10 ] => Diez )
?>

Updated code of ‘indioeuropeo’ with option to input string-based keys.

Here is a function to find out the maximum depth of a multidimensional array.

// return depth of given array
// if Array is a string ArrayDepth() will return 0
// usage: int ArrayDepth(array Array)

Short function for making a recursive array copy while cloning objects on the way.

If you need to flattern two-dismensional array with single values assoc subarrays, you could use this function:

to 2g4wx3:
i think better way for this is using JSON, if you have such module in your PHP. See json.org.

to convert JS array to JSON string: arr.toJSONString();
to convert JSON string to PHP array: json_decode($jsonString);

You can also stringify objects, numbers, etc.

Function to pretty print arrays and objects. Detects object recursion and allows setting a maximum depth. Based on arraytostring and u_print_r from the print_r function notes. Should be called like so:

I was looking for an array aggregation function here and ended up writing this one.

Note: This implementation assumes that none of the fields you’re aggregating on contain The ‘@’ symbol.

While PHP has well over three-score array functions, array_rotate is strangely missing as of PHP 5.3. Searching online offered several solutions, but the ones I found have defects such as inefficiently looping through the array or ignoring keys.

Источник

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

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