Определите, является ли массив ассоциативным (хэш) или нет

Я хотел бы иметь возможность передать массив функции, и функция будет вести себя по-разному в зависимости от того, массив массивов «списка» или массив «хэш». Например:

myfunc(array("One", "Two", "Three")); // works myfunc(array(1=>"One", 2=>"Two", 3=>"Three")); also works, but understands it's a hash 

Может выдавать что-то вроде:

 One, Two, Three 1=One, 2=Two, 3=Three 

т.е.: функция делает что-то по-другому, когда она «обнаруживает», что ей передается хеш, а не массив. Можете ли вы сказать, что я исхожу из фона Perl, где% хэшей – это разные ссылки из @arrays?

Я считаю, что мой пример значителен, потому что мы не можем просто проверить, является ли ключ числовым, потому что вы вполне можете использовать числовые ключи в своем хэше.

Я специально стараюсь избегать использования беспорядочной конструкции myfunc(array(array(1=>"One"), array(2=>"Two"), array(3=>"Three")))

Вытащил прямо из рамки коханы.

 public static function is_assoc(array $array) { // Keys of the array $keys = array_keys($array); // If the array keys of the keys match the keys, then the array must // not be associative (eg the keys array looked like {0:0, 1:1...}). return array_keys($keys) !== $keys; } 

Этот тест дает 3 метода.

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

1. Использование array_values ​​()

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

2. Использование array_keys ()

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

3. Использование array_filter ()

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

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

 if (array_keys($array) === range(0, count($array) - 1)) { //it is a hash } 

Нет, PHP не отличает массивы, где ключи являются числовыми строками из массивов, где ключи являются целыми числами в следующих случаях:

 $a = array("0"=>'a', "1"=>'b', "2"=>'c'); $b = array(0=>'a', 1=>'b', 2=>'c'); var_dump(array_keys($a), array_keys($b)); 

Он выводит:

 array(3) { [0]=> int(0) [1]=> int(1) [2]=> int(2) } array(3) { [0]=> int(0) [1]=> int(1) [2]=> int(2) } 

(выше для форматирования для удобочитаемости)

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

 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" ) 

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