Как проверить, является ли массив PHP ассоциативным или последовательным?

640

PHP обрабатывает все массивы как ассоциативные, поэтому нет встроенных функций. Может ли кто-нибудь рекомендовать достаточно эффективный способ проверить, содержит ли массив только числовые ключи?

В принципе, я хочу иметь возможность различать это:

$sequentialArray = array('apple', 'orange', 'tomato', 'carrot');

и это:

$assocArray = array('fruit1' => 'apple', 
                    'fruit2' => 'orange', 
                    'veg1' => 'tomato', 
                    'veg2' => 'carrot');
  • 293
    В вашем коде есть ошибка: помидор - это фрукт.
  • 3
    У этого метода есть предостережения, но часто я просто делаю if (isset($array[0])) , что просто и быстро. Конечно, вы должны сначала убедиться, что массив не пустой, и у вас должны быть некоторые знания о возможном содержимом массива, чтобы метод не мог завершиться с ошибкой (например, смешанный числовой / ассоциативный или непоследовательный).
Теги:
arrays

45 ответов

414
Лучший ответ

Вы задали два вопроса, которые не совсем эквивалентны:

  • Во-первых, как определить, имеет ли массив только числовые клавиши
  • Во-вторых, как определить, имеет ли массив последовательные числовые клавиши, начиная с 0

Подумайте, какое из этих поведений вам действительно нужно. (Возможно, это будет либо для ваших целей.)

Первый вопрос (просто проверка того, что все ключи являются числовыми) ответил хорошо капитаном kurO.

Для второго вопроса (проверяя, является ли массив нулевым индексом и последовательным), вы можете использовать следующую функцию:

function isAssoc(array $arr)
{
    if (array() === $arr) return false;
    return array_keys($arr) !== range(0, count($arr) - 1);
}

var_dump(isAssoc(array('a', 'b', 'c'))); // false
var_dump(isAssoc(array("0" => 'a', "1" => 'b', "2" => 'c'))); // false
var_dump(isAssoc(array("1" => 'a', "0" => 'b', "2" => 'c'))); // true
var_dump(isAssoc(array("a" => 'a', "b" => 'b', "c" => 'c'))); // true
  • 23
    Очень элегантное решение. Обратите внимание, что он возвращает TRUE в (неоднозначном) случае пустого массива.
  • 22
    Я думаю, что более полезно думать о последовательных массивах как об особом случае ассоциативных массивов. Таким образом, каждый массив является ассоциативным, но только некоторые являются последовательными. Поэтому функция isSequential() будет иметь больше смысла, чем isAssoc() . В такой функции пустой массив должен рассматриваться как последовательный. Формула может быть array() === $arr || !isAssoc($arr) .
Показать ещё 4 комментария
366

Чтобы просто проверить, имеет ли массив нецелые ключи (а не индексируется ли массив индексированным или нулевым индексом):

function has_string_keys(array $array) {
  return count(array_filter(array_keys($array), 'is_string')) > 0;
}

Если есть хотя бы один строковый ключ, $array будет рассматриваться как ассоциативный массив.

  • 19
    Этот метод намного лучше, чем кажется. Если count (filter_array) == count (original_array), то это массив ассоциаций. Если count (Filter_array) == 0, то это индексированный массив. Если count (filter_array) <count (original_array), то массив имеет как числовые, так и строковые ключи.
  • 0
    Способ замедлить Это будет повторять и применять функцию. Посмотрите ниже для более быстрых альтернатив или просто проверьте первый ключ для того, чтобы быть int.
Показать ещё 4 комментария
117

Конечно, это лучшая альтернатива.

<?php
$arr = array(1,2,3,4);
$isIndexed = array_values($arr) === $arr;
  • 46
    Это дублирует значения в массиве, что потенциально очень дорого. Вам намного лучше исследовать ключи массива.
  • 0
    Если одно из значений массива не установлено, этот код больше не возвращает действительный результат (например, unset ($ arr [0]); $ isIndexed = array_values ($ arr) === $ arr; // возвращает false.)
Показать ещё 6 комментариев
72

Многие комментаторы в этом вопросе не понимают, как массивы работают в PHP. Из документации :

Ключ может быть целым числом или строкой. Если ключ является стандартным представлением целого числа, он будет интерпретироваться как таковой (т.е. "8" будет интерпретироваться как 8, а "08" будет интерпретироваться как "08" ). Поплавки в ключе усекаются до целого. Индексированные и ассоциативные типы массивов являются одним и тем же типом в PHP, которые могут содержать как целые, так и строковые индексы.

Другими словами, нет такой вещи, как ключ массива "8", потому что он всегда будет (молча) преобразован в целое число 8. Поэтому попытка различать целые числа и числовые строки не требуется.

Если вам нужен наиболее эффективный способ проверки массива для нецелочисленных ключей, не делая копию части массива (например, array_keys()) или все это (например, foreach):

for (reset($my_array); is_int(key($my_array)); next($my_array));
$onlyIntKeys = is_null(key($my_array));

Это работает, потому что key() возвращает NULL, когда текущая позиция массива недействительна, и NULL никогда не может быть допустимым ключом (если вы попытаетесь использовать NULL в качестве ключа массива, он будет беззвучно преобразован в "").

  • 0
    Это не работает для непоследовательных целочисленных ключей. Попробуйте это с [2 => 'a', 4 => 'b'].
  • 1
    @DavidJ, что ты имеешь в виду под "не работает"? Он успешно определяет, что все ключи являются целыми числами. Вы утверждаете, что массив, подобный тому, который вы разместили, не должен рассматриваться как "числовой массив"?
Показать ещё 4 комментария
31

Как указанный OP:

PHP обрабатывает все массивы как ассоциативные

не совсем разумно (IMHO) написать функцию, которая проверяет, является ли массив ассоциативным. Итак, прежде всего: что такое ключ в массиве PHP:

Ключ может быть либо целым числом, либо строкой.

Это означает, что возможны 3 случая:

  • Случай 1. все клавиши числовые/ целые числа.
  • Случай 2. все клавиши строки.
  • Случай 3. Некоторые клавиши строки, некоторые клавиши числовые/ целые числа.

Мы можем проверить каждый случай со следующими функциями.

Случай 1: все клавиши числовые/ целые числа.

Примечание. Эта функция возвращает true для пустых массивов.

//! Check whether the input is an array whose keys are all integers.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array whose keys are all integers.
*/
function IsArrayAllKeyInt($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return array_unique(array_map("is_int", array_keys($InputArray))) === array(true);
}

Случай 2: все клавиши строки.

Примечание. Эта функция возвращает true для пустых массивов.

//! Check whether the input is an array whose keys are all strings.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array whose keys are all strings.
*/
function IsArrayAllKeyString($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return array_unique(array_map("is_string", array_keys($InputArray))) === array(true);
}

Случай 3. Некоторые клавиши строки, некоторые клавиши числовые/ целые числа.

Примечание. Эта функция возвращает true для пустых массивов.

//! Check whether the input is an array with at least one key being an integer and at least one key being a string.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array with at least one key being an integer and at least one key being a string.
*/
function IsArraySomeKeyIntAndSomeKeyString($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return count(array_unique(array_map("is_string", array_keys($InputArray)))) >= 2;
}

Отсюда следует, что:


Теперь, чтобы массив был "подлинным" массивом, к которому мы все привыкли, это означает:

  • Его ключи - это числовые/ целые числа.
  • Его ключи последовательно (т.е. увеличиваются на шаг 1).
  • Его ключи начать с нуля.

Мы можем проверить со следующей функцией.

Случай 3a. клавиши числовые/ целые числа, последовательные и нулевые.

Примечание. Эта функция возвращает true для пустых массивов.

//! Check whether the input is an array whose keys are numeric, sequential, and zero-based.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array whose keys are numeric, sequential, and zero-based.
*/
function IsArrayKeyNumericSequentialZeroBased($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return array_keys($InputArray) === range(0, count($InputArray) - 1);
}

Предостережения/Ловушки (или еще более странные факты о ключах массива в PHP)

Целочисленные клавиши

Ключи для этих массивов целые числа:

array(0 => "b");
array(13 => "b");
array(-13 => "b");          // Negative integers are also integers.
array(0x1A => "b");         // Hexadecimal notation.

Строковые клавиши

Ключами для этих массивов являются строки:

array("fish and chips" => "b");
array("" => "b");                                   // An empty string is also a string.
array("[email protected]" => "b");    // Strings may contain non-alphanumeric characters.
array("stack\t\"over\"\r\nflow cool" => "b");     // Strings may contain special characters.
array('$tα€køv∈rflöw' => "b");                    // Strings may contain all kinds of symbols.
array("functіon" => "b");                           // You think this looks fine? Think again! (see https://stackoverflow.com/q/9246051/1402846)
array("ま말轉转ДŁ" => "b");                         // How about Japanese/Korean/Chinese/Russian/Polish?
array("fi\x0sh" => "b");                            // Strings may contain null characters.
array(file_get_contents("https://www.google.com/images/nav_logo114.png") => "b");   // Strings may even be binary!

Целочисленные ключи, которые выглядят как строки

Если вы считаете, что ключ в array("13" => "b") является строкой, вы ошибаетесь. Из документа здесь:

Строки, содержащие действительные целые числа, будут переданы в целочисленный тип. Например. ключ "8" будет фактически сохранен под 8. С другой стороны, "08" не будет выбрано, так как оно не является допустимым десятичным целым.

Например, ключ для этих массивов целые числа:

array("13" => "b");
array("-13" => "b");                        // Negative, ok.

Но ключом для этих массивов являются строки:

array("13." => "b");
array("+13" => "b");                        // Positive, not ok.
array("-013" => "b");
array("0x1A" => "b");                       // Not converted to integers even though it a valid hexadecimal number.
array("013" => "b");                        // Not converted to integers even though it a valid octal number.
array("18446744073709551616" => "b");       // Not converted to integers as it can't fit into a 64-bit integer.

Что еще, в соответствии с doc,

Размер целого числа зависит от платформы, хотя максимальное значение около двух миллиардов - это обычное значение (это 32 бита). 64-разрядные платформы обычно имеют максимальное значение около 9E18, за исключением Windows, которая всегда 32 бит. PHP не поддерживает целые числа без знака.

Таким образом, ключ для этого массива может или не может быть целым числом - это зависит от вашей платформы.

array("60000000000" => "b");                // Array key could be integer or string, it can fit into a 64-bit (but not 32-bit) integer.

Хуже того, PHP имеет тенденцию быть багги, если целое число находится рядом с границей 2 31= 2,147,483,648 (см. ошибка 51430, ошибка 52899). Например, в моей локальной среде (PHP 5.3.8 на XAMPP 1.7.7 в Windows 7) var_dump(array("2147483647" => "b")) дает

array(1) {
    [2147483647]=>
    string(1) "b"
}   

но на эта живая демонстрация в кодедепе (PHP 5.2.5), то же выражение дает

array(1) {
    ["2147483647"]=>
    string(1) "b"
}

Таким образом, ключ является целым числом в одной среде, но строка в другой, хотя 2147483647 является действительным подписанным 32-битным целым числом.

  • 2
    За исключением того, что, как я упоминаю ниже, это включает создание дублирующего массива для проверяемого массива, что делает его очень дорогим для больших массивов и потенциальным источником сбоя нехватки памяти на общих хостах.
31

Speed-накрест:

function isAssoc($array)
{
    return ($array !== array_values($array));
}

Память-накрест:

function isAssoc($array)
{
    $array = array_keys($array); return ($array !== array_keys($array));
}
  • 7
    Вот тест производительности для вышеупомянутого: gist.github.com/1965669
  • 0
    следующий массив: массив (02 => 11,1,2,456); отображается как не имеющий числовых ключей с использованием вышеуказанного алгоритма, даже если 02 === 2
19
function checkAssoc($array){
    return  ctype_digit( implode('', array_keys($array) ) );
}
  • 2
    Это единственный ответ (на момент моего комментария), который может касаться следующего: $ array = array (0 => 'blah', 2 => 'yep', 3 => 'wahey')
  • 8
    Это работает, если один из ключей является пустой строкой?
Показать ещё 4 комментария
17

Фактически наиболее эффективным способом является:

function is_assoc($array){
   $keys = array_keys($array);
   return $keys !== array_keys($keys);
}

Это работает, потому что он сравнивает ключи (которые для последовательного массива всегда равны 0,1,2 и т.д.) для ключей ключей (которые всегда будут 0,1,2 и т.д.).

  • 1
    Умно, но не хорошо. Почему это «самый эффективный»? Было бы намного удобнее сравнивать array_keys ($ a) с диапазоном (0, count ($ a)). Самое умное решение редко бывает лучшим в моем опыте. Особенно, когда умный добавляет буквально никакой ценности по сравнению с очевидной и чистой альтернативой.
  • 4
    Эта функция возвращает true для array(1=>"a") но false для array("a"=>"a") . Будет более значимым, если != Будет заменен на !== .
Показать ещё 2 комментария
16

Я использовал как array_keys($obj) !== range(0, count($obj) - 1), так и array_values($arr) !== $arr (которые являются дуальными друг от друга, хотя второй дешевле первого), но оба не работают для очень больших массивов.

Это связано с тем, что array_keys и array_values являются очень дорогостоящими операциями (поскольку они строят целый новый массив размера, примерно такой же, как у оригинала).

Следующая функция более надежна, чем приведенные выше методы:

function array_type( $obj ){
    $last_key = -1;
    $type = 'index';
    foreach( $obj as $key => $val ){
        if( !is_int( $key ) || $key < 0 ){
            return 'assoc';
        }
        if( $key !== $last_key + 1 ){
            $type = 'sparse';
        }
        $last_key = $key;
    }
    return $type;
}

Также обратите внимание, что если вы не хотите отличать разреженные массивы от ассоциативных массивов, вы можете просто вернуть 'assoc' из обоих блоков if.

Наконец, хотя это может показаться намного менее "элегантным", чем множество "решений" на этой странице, на практике это значительно более эффективно. Почти любой ассоциативный массив будет обнаружен мгновенно. Только индексированные массивы будут проверяться исчерпывающе, и описанные выше методы не только полностью проверяют индексированные массивы, но и дублируют их.

13

Я думаю, что следующие две функции - лучший способ проверить "если массив ассоциативный или числовой". Поскольку "числовые" могут означать только цифровые клавиши или только последовательные цифровые клавиши, ниже перечислены две функции, которые проверяют либо условие:

function is_indexed_array(&$arr) {
  for (reset($arr); is_int(key($arr)); next($arr));
  return is_null(key($arr));
}

function is_sequential_array(&$arr, $base = 0) {
  for (reset($arr), $base = (int) $base; key($arr) === $base++; next($arr));
  return is_null(key($arr));
}

Первая функция проверяет, является ли каждая клавиша целочисленным значением. Вторая функция проверяет, является ли каждый ключ целочисленным значением и дополнительно проверяет, все ли ключи последовательны, начиная с $base, по умолчанию 0, и, следовательно, можно опустить, если вам не нужно указывать другое базовое значение. key ($ my_array) возвращает null, если указатель чтения перемещается за конец массива, что и заканчивает цикл for, и делает оператор после того, как цикл for возвращает true, если все ключи были целыми. Если нет, цикл заканчивается преждевременно, потому что ключ имеет строку типа, а оператор после цикла for возвращает false. Последняя функция дополнительно добавляет от одной до $базы после каждого сравнения, чтобы проверить, имеет ли следующий ключ правильное значение. Строгое сравнение также позволяет проверить, имеет ли ключ целочисленный тип. Базовая часть $base = (int) $в первом разделе цикла for может быть опущена, когда $base опущена или если вы убедитесь, что она вызывается только с помощью целого числа. Но так как я не могу быть уверен в всех, я оставил его. Заявление выполняется только один раз. Я думаю, что это наиболее эффективные решения:

  • Память: Нет копирования данных или диапазонов клавиш. Выполнение array_values ​​или array_keys может казаться короче (меньше кода), но имейте в виду, что происходит в фоновом режиме после того, как вы сделаете этот вызов. Да, есть больше (видимых) заявлений, чем в некоторых других решениях, но это не так важно, не так ли?
  • Время: кроме того, что копирование/извлечение данных и/или ключей также требует времени, это решение более эффективно, чем выполнение foreach. Опять же, foreach может показаться более эффективным для некоторых, потому что он короче в нотации, но на заднем плане foreach также вызывает reset, key и next, чтобы сделать это циклическим. Но, кроме того, он также вызывает действие для проверки конечного условия, чего здесь можно избежать из-за комбинации с цельной проверкой.

Помните, что ключ массива может быть только целым числом или строкой, а строчная числовая строка, такая как "1" (но не "01" ), будет переведена в целое число. Это то, что делает проверку целочисленного ключа единственной необходимой операцией, кроме подсчета, если вы хотите, чтобы массив был последовательным. Естественно, если is_indexed_array возвращает false, массив можно рассматривать как ассоциативный. Я говорю "видел", потому что на самом деле все они есть.

  • 1
    Это лучший ответ. Определение «ассоциативного» или «числового» массива зависит от конкретной ситуации.
7

Эта функция может обрабатывать:

  • с отверстиями в индексе (например, 1,2,4,5,8,10)
  • с клавишами "0x": например. ключ "08" ассоциативен, а ключ "8" является последовательным.

идея проста: если один из ключей НЕ является целым числом, это ассоциативный массив, в противном случае он последователен.

function is_asso($a){
    foreach(array_keys($a) as $key) {if (!is_int($key)) return TRUE;}
    return FALSE;
}
  • 1
    «если один из ключей НЕ является целым числом, это ассоциативный массив, в противном случае он является последовательным» - а? Нет, это просто неправильно. Есть место для споров по поводу того, что составляет «ассоциативный» массив, но значение «последовательный» довольно однозначно, и это не то же самое, что все ключи являются числами.
  • 0
    Если один из ключей НЕ является целым числом, он по своей природе является ассоциативным, однако он будет последовательным только в том случае, если ключи идут от 0 - длина (массив) - 1. Однако он ЦИФРОВОЙ, если все ключи только пронумерованы, но может или может не работать со многими функциями массива, которые требуют последовательного массива. Если вы преобразуете числовой массив с отверстиями в последовательный, запустив на нем array_values (array), он будет преобразован в последовательный.
6

Я заметил два популярных подхода к этому вопросу: один использовал array_values() и другие, используя key(). Чтобы узнать, что быстрее, я написал небольшую программу:

$arrays = Array(
  'Array #1' => Array(1, 2, 3, 54, 23, 212, 123, 1, 1),
  'Array #2' => Array("Stack", 1.5, 20, Array(3.4)),
  'Array #3' => Array(1 => 4, 2 => 2),
  'Array #4' => Array(3.0, "2", 3000, "Stack", 5 => "4"),
  'Array #5' => Array("3" => 4, "2" => 2),
  'Array #6' => Array("0" => "One", 1.0 => "Two", 2 => "Three"),
  'Array #7' => Array(3 => "asdf", 4 => "asdf"),
  'Array #8' => Array("apple" => 1, "orange" => 2),
);

function is_indexed_array_1(Array &$arr) {
  return $arr === array_values($arr);
}

function is_indexed_array_2(Array &$arr) {
  for (reset($arr), $i = 0; key($arr) === $i++; next($arr))
    ;
  return is_null(key($arr));
}

// Method #1
$start = microtime(true);
for ($i = 0; $i < 1000; $i++) {
  foreach ($arrays as $array) {
    $dummy = is_indexed_array_1($array);
  }
}
$end = microtime(true);
echo "Time taken with method #1 = ".round(($end-$start)*1000.0,3)."ms\n";

// Method #2
$start = microtime(true);
for ($i = 0; $i < 1000; $i++) {
  foreach ($arrays as $array) {
    $dummy = is_indexed_array_2($array);
  }
}
$end = microtime(true);
echo "Time taken with method #1 = ".round(($end-$start)*1000.0,3)."ms\n";

Вывод для программы на PHP 5.2 на CentOS выглядит следующим образом:

Время, затраченное на метод # 1 = 10,745мс
Время, затраченное на метод # 2 = 18.239мс

Результат на PHP 5.3 дал аналогичные результаты. Очевидно, что использование array_values() выполняется намного быстрее.

  • 0
    плохой тест Вы не проверяли большие массивы. На моем компьютере, начиная с 10K + элементов, метод № 2 быстрее. Попробуйте с $arrays = Array( 'Array #1' => range(0, 50000), );
  • 0
    @nonsensei Поделитесь своими выводами / результатами тестов
Показать ещё 1 комментарий
3

Используя xarray Расширение PHP

Вы можете сделать это очень быстро (примерно в 30 + раз быстрее в PHP 5.6):

if (array_is_indexed($array)) {  }

Или:

if (array_is_assoc($array)) {  }
3

Мое решение:

function isAssociative(array $array)
{
    return array_keys(array_merge($array)) !== range(0, count($array) - 1);
}

array_merge в одном массиве будет переинсталлировать все клавиши integer, но не другие. Например:

array_merge([1 => 'One', 3 => 'Three', 'two' => 'Two', 6 => 'Six']);

// This will returns [0 => 'One', 1 => 'Three', 'two' => 'Two', 2 => 'Six']

Итак, если создается список (неассоциативный массив) ['a', 'b', 'c'], тогда значение удаляется unset($a[1]), тогда вызывается array_merge, список переиндексируется, начиная с 0.

  • 0
    -1; это O(n) в используемой дополнительной памяти (поскольку он создал несколько новых массивов с таким количеством элементов, как $array ), ответ не решает неоднозначность вопроса, который был задан, и не объясняет, как именно он определяет список / не -ассоциативный массив, и даже если ни одна из этих точек не соответствует действительности, неясно, добавляет ли это какую-либо ценность по сравнению с другими уже опубликованными ответами.
3

Это тоже сработает (demo):

function array_has_numeric_keys_only(array $array)
{
    try {
        SplFixedArray::fromArray($array, true);
    } catch (InvalidArgumentException $e) {
        return false;
    }
    return true;
}

Обратите внимание, что основная часть этого ответа состоит в том, чтобы сообщить вам о существовании SplFixedArray и не поощрять использование исключений для этих видов тестов.

3

Если PHP не имеет встроенного для этого, вы не сможете сделать это меньше, чем O (n) - перечислите все ключи и проверите для целочисленного типа. Фактически, вы также хотите убедиться, что нет отверстий, поэтому ваш алгоритм может выглядеть так:

for i in 0 to len(your_array):
    if not defined(your-array[i]):
        # this is not an array array, it an associative array :)

Но зачем беспокоиться? Предположим, что массив имеет тот тип, который вы ожидаете. Если это не так, это просто взорвется вам в лицо - это динамическое программирование для вас! Проверьте свой код, и все будет хорошо...

  • 1
    Обычно, если предположить, что массив является желаемым типом, это то, что нужно. Но в моем случае я перебираю многомерный массив и форматирую вывод в зависимости от типа массива данного узла.
2
function array_is_assoc(array $a) {
    $i = 0;
    foreach ($a as $k => $v) {
        if ($k !== $i++) {
            return true;
        }
    }
    return false;
}

Быстрая, лаконичная и эффективная память. Нет дорогостоящих сравнений, вызовов функций или копирования массивов.

2

Я думаю, что определение скалярного массива будет отличаться в зависимости от приложения. То есть для некоторых приложений требуется более строгое представление о том, что квалифицируется как скалярный массив, а для некоторых приложений требуется более свободный смысл.

Ниже представлены 3 метода различной строгости.

<?php
/**
 * Since PHP stores all arrays as associative internally, there is no proper
 * definition of a scalar array.
 * 
 * As such, developers are likely to have varying definitions of scalar array,
 * based on their application needs.
 * 
 * In this file, I present 3 increasingly strict methods of determining if an
 * array is scalar.
 * 
 * @author David Farrell <[email protected]>
 */

/**
 * isArrayWithOnlyIntKeys defines a scalar array as containing
 * only integer keys.
 * 
 * If you are explicitly setting integer keys on an array, you
 * may need this function to determine scalar-ness.
 * 
 * @param array $a
 * @return boolean
 */ 
function isArrayWithOnlyIntKeys(array $a)
{
    if (!is_array($a))
        return false;
    foreach ($a as $k => $v)
        if (!is_int($k))
            return false;
    return true;
}

/**
 * isArrayWithOnlyAscendingIntKeys defines a scalar array as
 * containing only integer keys in ascending (but not necessarily
 * sequential) order.
 * 
 * If you are performing pushes, pops, and unsets on your array,
 * you may need this function to determine scalar-ness.
 * 
 * @param array $a
 * @return boolean
 */ 
function isArrayWithOnlyAscendingIntKeys(array $a)
{
    if (!is_array($a))
        return false;
    $prev = null;
    foreach ($a as $k => $v)
    {
        if (!is_int($k) || (null !== $prev && $k <= $prev))
            return false;
        $prev = $k;
    }
    return true;
}

/**
 * isArrayWithOnlyZeroBasedSequentialIntKeys defines a scalar array
 * as containing only integer keys in sequential, ascending order,
 * starting from 0.
 * 
 * If you are only performing operations on your array that are
 * guaranteed to either maintain consistent key values, or that
 * re-base the keys for consistency, then you can use this function.
 * 
 * @param array $a
 * @return boolean
 */
function isArrayWithOnlyZeroBasedSequentialIntKeys(array $a)
{
    if (!is_array($a))
        return false;
    $i = 0;
    foreach ($a as $k => $v)
        if ($i++ !== $k)
            return false;
    return true;
}
2
<?php

function is_list($array) {
    return array_keys($array) === range(0, count($array) - 1);
}

function is_assoc($array) {
    return count(array_filter(array_keys($array), 'is_string')) == count($array);
}

?>

Оба этих примера, которые набрали наибольшее количество баллов, не работают корректно с массивами вроде $array = array('foo' => 'bar', 1)

  • 0
    +1 Ваш is_list () - IMO лучший ответ. Некоторые люди не имеют ни малейшего представления о сложности времени и пространства, а о нативной и PHP-скриптовой функции ...
2

Здесь используется метод, который я использую:

function is_associative ( $a )
{
    return in_array(false, array_map('is_numeric', array_keys($a)));
}

assert( true === is_associative(array(1, 2, 3, 4)) );

assert( false === is_associative(array('foo' => 'bar', 'bar' => 'baz')) );

assert( false === is_associative(array(1, 2, 3, 'foo' => 'bar')) );

Обратите внимание, что это не учитывает особые случаи, например:

$a = array( 1, 2, 3, 4 );

unset($a[1]);

assert( true === is_associative($a) );

Извините, не могу с этим поделать. Он также несколько эффективен для приличных размеров массивов, поскольку он не делает ненужных копий. Именно эти мелочи делают Python и Ruby гораздо приятнее писать в...: P

2

Может ли это быть решением?

  public static function isArrayAssociative(array $array) {
      reset($array);
      return !is_int(key($array));
  }

Предостережение очевидно, что курсор массива reset, но я бы сказал, вероятно, что функция используется до того, как массив прошел или используется.

  • 0
    Эта функция возвращает false как для array("a", "b") и для array("a", "b" => "B") поскольку она проверяет только первый ключ. Кстати, is_long это просто псевдоним is_int .
  • 1
    Откровенно говоря, я думаю, что это было бы очень эффективно в подавляющем большинстве случаев и гораздо более эффективно, чем альтернативы. Если вы понимаете последствия этого метода и понимаете, что он будет работать на вас, это, вероятно, лучший выбор.
Показать ещё 4 комментария
1

Уже есть много ответов, но вот метод, который Laravel использует в своем классе Arr:

    /**
 * Determines if an array is associative.
 *
 * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
 *
 * @param  array  $array
 * @return bool
 */
public static function isAssoc(array $array)
{
    $keys = array_keys($array);

    return array_keys($keys) !== $keys;
}

Источник: https://github.com/laravel/framework/blob/5.4/src/Illuminate/Support/Arr.php

  • 1
    Почему это работает?
  • 1
    @Casey array_keys($keys) вернет последовательный массив чисел (0 ... X), который имеет ту же длину исходного массива. Например, array_keys(["a", "b", "c"]) = [0, 1, 2]; array_keys([0, 1, 2]) = [0, 1, 2] (это последовательный массив, потому что [0, 1, 2] !== [0, 1, 2] ). Другой пример: array_keys(["a" => 5, "b" => 7, "c" => 10]) = ["a", "b", "c"]; array_keys(["a", "b", "c"]) = [0, 1, 2] (это ассоциативный массив, потому что ["a", "b", "c"] !== [0, 1, 2] ). Надеюсь, это понятно (сложно объяснить в комментариях, по крайней мере, для меня)
Показать ещё 2 комментария
1

ответы уже даны, но слишком много дезинформации о производительности. Я написал этот маленький тест script, который показывает, что метод foreach является самым быстрым.

Отказ от ответственности: следующие методы были скопированы с других ответов

<?php

function method_1(Array &$arr) {
    return $arr === array_values($arr);
}

function method_2(Array &$arr) {
    for (reset($arr), $i = 0; key($arr) !== $i++; next($arr));
    return is_null(key($arr));
}

function method_3(Array &$arr) {
    return array_keys($arr) === range(0, count($arr) - 1);
}

function method_4(Array &$arr) {
    $idx = 0;
    foreach( $arr as $key => $val ){
        if( $key !== $idx )
            return FALSE;
        $idx++;
    }
    return TRUE;
}




function benchmark(Array $methods, Array &$target){    
    foreach($methods as $method){
        $start = microtime(true);
        for ($i = 0; $i < 1000; $i++)
            $dummy = call_user_func($method, $target);

        $end = microtime(true);
        echo "Time taken with $method = ".round(($end-$start)*1000.0,3)."ms\n";
    }
}



$targets = [
    'Huge array' => range(0, 30000),
    'Small array' => range(0, 1000),
];
$methods = [
    'method_1',
    'method_2',
    'method_3',
    'method_4',
];
foreach($targets as $targetName => $target){
    echo "==== Benchmark using $targetName ====\n";
    benchmark($methods, $target);
    echo "\n";
}

результаты:

==== Benchmark using Huge array ====
Time taken with method_1 = 5504.632ms
Time taken with method_2 = 4509.445ms
Time taken with method_3 = 8614.883ms
Time taken with method_4 = 2720.934ms

==== Benchmark using Small array ====
Time taken with method_1 = 77.159ms
Time taken with method_2 = 130.03ms
Time taken with method_3 = 160.866ms
Time taken with method_4 = 69.946ms
1

Один из способов приблизиться к этому - связать с json_encode, у которого уже есть свой собственный внутренний метод дифференциации ассоциативного массива и индексированного массива для вывода правильного JSON.

Вы можете сделать это, проверив, является ли первый символ, возвращаемый после кодирования, { (ассоциативный массив) или [ (индексированный массив).

echo substr(json_encode($the_array), 0, 1) == '{' ? 'yes' : 'no';
  • 0
    На мой взгляд, ksort () не нужен. Это решение работает, но оно должно проверить, имеет ли $ arr значение NULL и не работает ли json_encode, так что попытайтесь / поймайте. + это не совсем оптимально, если $ arr велико.
1

Еще один быстрый из источник. Установите кодировку json_encodebson_encode). Таким образом, соответствие javascript Array.

function isSequential($value){
    if(is_array($value) || ($value instanceof \Countable && $value instanceof \ArrayAccess)){
        for ($i = count($value) - 1; $i >= 0; $i--) {
            if (!isset($value[$i]) && !array_key_exists($i, $value)) {
                return false;
            }
        }
        return true;
    } else {
        throw new \InvalidArgumentException(
            sprintf('Data type "%s" is not supported by method %s', gettype($value), __METHOD__)
        );
    }
}
  • 1
    Почему isset и array_key_exists ? Разве последнего не будет достаточно?
  • 0
    @mcfedr да, было бы - проверка isset() здесь полностью избыточна.
Показать ещё 5 комментариев
1

Я знаю это немного бессмысленно, добавляя ответ на эту огромную очередь, но здесь читаемое O (n) решение, которое не требует дублирования любых значений:

function isNumericArray($array) {
    $count = count($array);
    for ($i = 0; $i < $count; $i++) {
        if (!isset($array[$i])) {
            return FALSE;
        }
    }
    return TRUE;
}

Вместо того, чтобы проверять ключи, чтобы увидеть, все ли они числовые, вы перебираете ключи, которые будут там для числового массива, и убедитесь, что они существуют.

  • 0
    еще один момент. массив в форме [1,2,null,4] потерпит неудачу, но это правильный массив. поэтому я добавил некоторые улучшения в stackoverflow.com/a/25206156/501831 с array_key_exists добавления array_key_exists )
  • 0
    -1; isset() здесь не тот инструмент, потому что он вернет false, если значение установлено, но имеет значение null , как указывает @lazycommit.
0

Проверка наличия массива всех связанных ключей. С помощью stdClass и get_object_vars ^):

$assocArray = array('fruit1' => 'apple', 
                    'fruit2' => 'orange', 
                    'veg1' => 'tomato', 
                    'veg2' => 'carrot');

$assoc_object = (object) $assocArray;
$isAssoc = (count($assocArray) === count (get_object_vars($assoc_object)));  
var_dump($isAssoc); // true

Почему? Функция get_object_vars возвращает только доступные свойства (подробнее о том, что происходит при конвертировании array в object здесь). Тогда просто логически: если количество элементов базового массива равно количество доступных свойств объекта - все ключи связаны.

Несколько тестов:

$assocArray = array('apple', 'orange', 'tomato', 'carrot');
$assoc_object = (object) $assocArray; 
$isAssoc = (count($assocArray) === count (get_object_vars($assoc_object)));
var_dump($isAssoc); // false 
//...

$assocArray = array( 0 => 'apple', 'orange', 'tomato', '4' => 'carrot');
$assoc_object = (object) $assocArray; 
$isAssoc = (count($assocArray) === count (get_object_vars($assoc_object)));
var_dump($isAssoc); // false 

//... 
$assocArray = array('fruit1' => 'apple', 
                    NULL => 'orange', 
                    'veg1' => 'tomato', 
                    'veg2' => 'carrot');

$assoc_object = (object) $assocArray;
$isAssoc = (count($assocArray) === count (get_object_vars($assoc_object)));  
var_dump($isAssoc); //false

Etc.

  • 0
    Это не работа. Доказательство eval.in/859508 $ asocArray - массив с двумя массивами. Верните истину. Другие доказательства для других, например, также не работают, как ваш латентный пример eval.in/859507 возвращает true
0

Простым способом вы можете проверить, является ли массив ассоциативным или нет по шагам

  • преобразовать все ключи массива в один массив с помощью array_keys()
  • отфильтровать нецифровой ключ из массива с помощью array_filter() и is_numeric()
  • сравнить количество элементов в фильтрованном массиве и фактическом массиве. Если количество элементов не равно в обоих массивах, то это ассоциативный массив.

Функция для вышеуказанного шага выглядит следующим образом.

 function isAssociative(array $array)
    {
        return count(array_filter(array_keys($array), function($v){return is_numeric($v);})) !== count($array));
    }
0

Улучшение от Mark Amery

function isAssoc($arr)
{
    // Is it set, is an array, not empty and keys are not sequentialy numeric from 0
    return isset($arr) && is_array($arr) && count($arr)!=0 && array_keys($arr) !== range(0, count($arr) - 1);
}

Это проверяет, существует ли переменная, если она является массивом, если она не является пустым массивом и если ключи не являются последовательными от 0.

Чтобы узнать, является ли массив ассоциативным

if (isAssoc($array)) ...

Чтобы узнать, является ли числовое число

if (!isAssoc($array)) ...
  • 0
    Подождите, что, где я сделал это? Или вы хотите сказать , «Улучшение на Марка Эмери», как и в улучшении на принятый ответ , который приписывается мне? Обратите внимание, что в последнем случае я не написал этот ответ - мои изменения в нем просто привели к тому, что алгоритм атрибуции авторства для постов вики-сообщества добавил мое имя.
0
function is_array_assoc($foo) {
    if (is_array($foo)) {
        return (count(array_filter(array_keys($foo), 'is_string')) > 0);
    }
    return false;
}
  • 0
    -1 за полное отсутствие объяснения. Сброс еще одного примера кода на вопрос, на который было дано 42 ответа, без объяснения того, почему предпочесть его альтернативам, абсолютно никому не помогает. Кроме того, учитывая неоднозначность вопроса и аргументы, которые обсуждались в комментариях, здесь необходимо некоторое объяснение того, как именно вы определяете «ассоциативный» или «последовательный» массив.
0

На мой взгляд, массив должен приниматься как ассоциативный, если какой-либо из его ключей не является целым числом, например. float numbers и пустую строку ''.

Также целые числа без последовательности должны рассматриваться как ассоциативные (0,2,4,6), потому что эти типы массивов не могут использоваться с такими циклами следующим образом:

$n =count($arr);
for($i=0,$i<$n;$i++) 

Вторая часть приведенной ниже функции проверяет, индексированы ли клавиши или нет. Она также работает для ключей с отрицательными значениями. Например (-1,0,1,2,3,4,5)

count() = 7 , max = 5, min=-1



if( 7 == (5-(-1)+1 ) // true
    return false; // array not associative


/** 
 * isAssoc Checks if an array is associative
 * @param $arr reference to the array to be checked
 * @return bool 
 */     
function IsAssoc(&$arr){
    $keys= array_keys($arr);
    foreach($keys as $key){
        if (!is_integer($key))
            return true;
    }
    // if all keys are integer then check if they are indexed
    if(count($arr) == (max($keys)-min($keys)+1))
        return false;
    else
        return true;
}
  • 1
    1. IsAssoc() возвращает false для массивов, отличных от нуля, например, array(91 => "a") (как указано в ответе). 2. IsAssoc() возвращает false, даже если ключи массива расположены не по порядку, например, array(1 => "a", 0 => "b", 2 => "c") .
  • 0
    -1; ваши рассуждения здесь не имеют смысла. Если, как вы предлагаете здесь, вы хотите иметь возможность циклически проходить по массиву, используя обычный цикл for с $i в качестве переменной цикла в диапазоне от 0 до count($arr) - 1 , тогда массив должен быть проиндексирован с нуля , а не просто последовательно индексируется. Тем не менее, ваш код просто проверяет, что массив последовательно индексируется.
0

Я встретил эту проблему еще раз несколько дней назад, и я решил воспользоваться специальным свойством array_merge:

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

function Is_Indexed_Arr($arr){
    $arr_copy = $arr;
    if((2*count($arr)) == count(array_merge($arr, $arr_copy))){
        return 1;
    }
    return 0;
}
0

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

<?php
//$a is a subset of $b
function isSubset($a, $b)
{
    foreach($a =>$v)
        if(array_search($v, $b) === false)
            return false;

    return true;

    //less effecient, clearer implementation. (uses === for comparison)
    //return array_intersect($a, $b) === $a;
}

function isAssoc($arr)
{
    return !isSubset(array_keys($arr), range(0, count($arr) - 1));
}

var_dump(isAssoc(array('a', 'b', 'c'))); // false
var_dump(isAssoc(array(1 => 'a', 0 => 'b', 2 => 'c'))); // false
var_dump(isAssoc(array("0" => 'a', "1" => 'b', "2" => 'c'))); // false 
//(use === in isSubset to get 'true' for above statement)
var_dump(isAssoc(array("a" => 'a', "b" => 'b', "c" => 'c'))); // true
?>
  • 0
    -1; это займет O(n²) время для завершения, учитывая последовательный массив размером n . Это будет ужасно неэффективно для достаточно больших массивов.
0

Я сравниваю разницу между ключами массива и ключами результата array_values ​​() массива, который всегда будет массивом с целыми индексами. Если ключи одинаковы, это не ассоциативный массив.

function isHash($array) {
    if (!is_array($array)) return false;
    $diff = array_diff_assoc($array, array_values($array));
    return (empty($diff)) ? false : true;
}
  • 0
    -1; это использует O(n) дополнительной памяти, когда $array имеет n элементов, и запись (someboolean) ? false : true вместо !someboolean ужасен и !someboolean .
0
function is_associative($arr) {
  return (array_merge($arr) !== $arr || count(array_filter($arr, 'is_string', ARRAY_FILTER_USE_KEY)) > 0);
}
  • 0
    implode принимает 2 аргумента, плюс, эта функция будет возвращать false для массива, определенного так: $ x = array ("1" => "b", "0" => "a");
  • 2
    Клеевой параметр implode () стал необязательным в PHP 4.3.0. Ваш пример массива - $ x = array ("1" => "b", "0" => "a"); - имеет ассоциативный индекс непоследовательных строк. is_associative () вернет true для этого массива, как и ожидалось.
Показать ещё 3 комментария
-1

Мое решение состоит в том, чтобы получить ключи массива, как показано ниже, и проверить, что если ключ не является целым числом:

private function is_hash($array) {
    foreach($array as $key => $value) {
        return ! is_int($key);
    }
    return false;
}

Неправильно получить array_keys хэш-массива, как показано ниже:

array_keys(array(
       "abc" => "gfb",
       "bdc" => "dbc"
       )
);

выведет:

array(
       0 => "abc",
       1 => "bdc"
)

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

  • 0
    Вопрос в том, как проверить, является ли массив последовательным . Массив array(1 => 'foo', 0 => 'bar') не является последовательным, но пройдет ваш тест. Чтобы понять, почему это json_encode($array) , попробуйте json_encode($array) с последовательными и ассоциативными массивами.
  • 0
    да, я думаю, я запутался и застрял с ответами выше. Который продолжал сравнивать array_keys с диапазоном и думал, что у них будет вывод, который является сравнением, хэш это или нет. Так что мой ответ - им, а также тем, кому кажется, что array_keys дает значения последовательно. это все. А также имя функции is_hash, так что да, она не говорит вам, является ли она последовательной или нет
-1

Простое и удобное в работе решение, которое проверяет только первый ключ.

function isAssoc($arr = NULL)
{
    if ($arr && is_array($arr))
    {
        foreach ($arr as $key => $val)
        {
            if (is_numeric($key)) { return true; }

            break;
        }
    }

    return false;
}
  • 1
    Эта функция возвращает true как для array("a", "b") и для array("a", "b" => "B") поскольку она проверяет только первый ключ (обратите внимание на return и break ).
-1

Лучшая функция для обнаружения ассоциативного массива (хэш-массив)

<?php
function is_assoc($arr) { return (array_values($arr) !== $arr); }
?>
  • 0
    не работает для одноэлементных ассоциативных массивов
  • 3
    Разве это не повторяющийся ответ?
Показать ещё 1 комментарий
-1

Я просто использую функцию key(). Обратите внимание:

<?php
var_dump(key(array('hello'=>'world', 'hello'=>'world'))); //string(5) "hello"
var_dump(key(array('world', 'world')));                  //int(0)
var_dump(key(array("0" => 'a', "1" => 'b', "2" => 'c'))); //int(0) who makes string sequetial keys anyway????
?>

Таким образом, просто проверяя false, вы можете определить, является ли массив ассоциативным или нет.

  • 1
    var_dump((bool)key(array(1=>"foo"))); возвращает истину. -1.
  • 0
    var_dump((bool)key(array("a"=>"foo"))) возвращает true ; var_dump((bool)key(array(""=>"foo"))) возвращает false . Кроме того, оба var_dump((bool)key(array("foo","bar"))) и var_dump((bool)key(array("0"=>"foo","a"=>"bar"))) возвращает false .
-1

Еще один способ сделать это.

function array_isassociative($array)
{
    // Create new Array,  Make it the same size as the input array
    $compareArray = array_pad(array(), count($array), 0);

    // Compare the two array_keys
    return (count(array_diff_key($array, $compareArray))) ? true : false;

}
-2

Собственно, я оказался в подобной ситуации, пытаясь взять массив и проанализировать его в XML. Имена элементов XML не могут начинаться с цифр - и обнаруженные фрагменты кода неправильно обрабатывали массивы с числовыми индексами.

Подробности о моей конкретной ситуации ниже

Ответ, приведенный выше на @null (http://stackoverflow.com/a/173589/293332), на самом деле был довольно черным. Я был встревожен тем, что его проголосовали за то, что те, кто не понимает регулярное выражение, ведут очень разочаровывающие жизни.

В любом случае, основываясь на его ответе, вот что я закончил:

/** 
 * Checks if an array is associative by utilizing REGEX against the keys
 * @param   $arr    <array> Reference to the array to be checked
 * @return  boolean
 */     
private function    isAssociativeArray( &$arr ) {
    return  (bool)( preg_match( '/\D/', implode( array_keys( $arr ) ) ) );
}

Смотрите Последовательности Escape PCRE и PCRE Синтаксис для более подробной информации.

Моя частная ситуация

Вот пример массива, с которым я имею дело:

Случай A
return  array(
    "GetInventorySummary"  => array(
        "Filters"  => array( 
            "Filter"  => array(
                array(
                    "FilterType"  => "Shape",
                    "FilterValue"  => "W",
                ),
                array(
                    "FilterType"  => "Dimensions",
                    "FilterValue"  => "8 x 10",
                ),
                array(
                    "FilterType"  => "Grade",
                    "FilterValue"  => "A992",
                ),
            ),
        ),
        "SummaryField"  => "Length",
    ),
);

Вывод состоит в том, что ключ filter является переменной. Например:

Случай B
return  array(
    "GetInventorySummary"  => array(
        "Filters"  => array( 
            "Filter"  => array(
                "foo"   =>  "bar",
                "bar"   =>  "foo",
            ),
        ),
        "SummaryField"  => "Length",
    ),
);

Почему мне нужен доц. Массивная проверка

Если массив, который я преобразовываю, похож на Случай A, то я хочу вернуть:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GetInventorySummary>
    <Filters>
        <Filter>
            <FilterType>Shape</FilterType>
            <FilterValue>W</FilterValue>
        </Filter>
        <Filter>
            <FilterType>Dimensions</FilterType>
            <FilterValue>8 x 10</FilterValue>
        </Filter>
        <Filter>
            <FilterType>Grade</FilterType>
             <FilterValue>A992</FilterValue>
        </Filter>
    </Filters>
    <SummaryField>Length</SummaryField>
</GetInventorySummary>

... Однако, если массив, который я преобразовываю, похож на Случай B, то, что я хочу вернуть:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GetInventorySummary>
    <Filters>
        <Filter>
            <foo>bar</foo>
            <bar>foo</bar>
        </Filter>
    </Filters>
    <SummaryField>Length</SummaryField>
</GetInventorySummary>
  • 1
    Это isAssociativeArray() возвращает false для array(4=>"four",9=>"nine") , array("002"=>"two","007"=>"james") и array("a", ""=>"empty", "b") , которые явно ассоциативны.
-2
function isAssoc($arr)
{
    $a = array_keys($arr);
    for($i = 0, $t = count($a); $i < $t; $i++)
    {
        if($a[$i] != $i)
        {
            return false;
        }
    }
    return true;
}
  • 0
    это предполагает, что массив проиндексирован от 0, что не обязательно является истиной и даст неверные результаты для массивов, таких как [10=>'x', 20=>'y']
  • 0
    Эта функция возвращает true как для array("a"=>"b") и для array("a","b") .
-2

Один дешевый и грязный способ - это проверить:

isset($myArray[count($myArray) - 1])

... вы можете получить ложное положительное значение, если ваш массив выглядит следующим образом:

$myArray = array("1" => "apple", "b" => "banana");

Более тщательный способ проверки ключей:

function arrayIsAssociative($myArray) {
    foreach (array_keys($myArray) as $ind => $key) {
        if (!is_numeric($key) || (isset($myArray[$ind + 1]) && $myArray[$ind + 1] != $key + 1)) {
            return true;
        }
    }
    return false;
}
// this will only return true if all the keys are numeric AND sequential, which
// is what you get when you define an array like this:
// array("a", "b", "c", "d", "e");

или

function arrayIsAssociative($myArray) {
    $l = count($myArray);
    for ($i = 0; $i < $l, ++$i) {
        if (!isset($myArray[$i])) return true;
    }
    return false;
}
// this will return a false positive on an array like this:
$x = array(1 => "b", 0 => "a", 2 => "c", 4 => "e", 3 => "d");
  • 0
    +1 за метод isset. Да, это грязно, но это единственный метод, который O (1) вместо O (n).
  • 1
    arrayIsAssociative() возвращает true для array("a", "b", "c") и array("a", "b"=>"b", "c") , но false для обоих array("a") и array(2=>"a") .
-3

Еще один вариант пока не показан, так как он просто не принимает числовые ключи, но мне очень нравится Greg:

 /* Returns true if $var associative array */  
  function is_associative_array( $array ) {  
    return is_array($array) && !is_numeric(implode('', array_keys($array)));  
  }
  • 0
    Эта функция возвращает false для array(2=>'a',3=>'b') , array('a','b') , array("0x"=>'a','f'=>'g') , array("90"=>'a',"17"=>'b') , array(""=>'b',20=>'c') .
  • 0
    @Pang: если бы вы могли читать: «это просто не принимает числовые ключи», вы могли бы просто удалить понижающее голосование. Спасибо.
Показать ещё 1 комментарий
-5

Если вы ищете только нечисловые ключи (независимо от порядка), вы можете попробовать

function IsAssociative($array)
{
    return preg_match('/[a-z]/i', implode(array_keys($array)));
}
  • 6
    -1 за то, что пропустил апостроф. Да, и тест с array("@"=>"foo"); , И ... правда , правда ?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню