2011-05-13 5 views
9

배열을 함수에 전달하고 함수가 "목록"스타일 배열인지 "해시"스타일인지에 따라 다르게 동작하게하고 싶습니다. 정렬. 예컨대 : 같은배열이 연관 (해시)인지 여부를 확인하십시오.

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 

예 : 그것은 배열이 아닌 해시를 전달되는 것 "감지"할 때 함수가 다르게 무언가를. @lrays와 % reference가 다른 Perl 백그라운드에서 온다고 말할 수 있습니까?

해시에서 숫자 키를 잘 사용할 수 있기 때문에 키가 숫자인지 테스트 할 수 없으므로 예제가 중요하다고 생각합니다.

내가 특별히 기술적으로 해시, 같은 myfunc(array(array(1=>"One"), array(2=>"Two"), array(3=>"Three")))

+2

이런 식으로 뭔가를 찾고 계십니까? http://stackoverflow.com/questions/173400/php-arrays-a-good-way-to-check-if-an-array-is-associative-or-sequential –

+0

흥미로운 질문입니다. 불행히도'array ('a', 'b', 'c')'를'array (0 => 'a', 1 => 'b', 2 => 'c')'와 구별하지 않는다. – Tadeck

+1

PHP는 항상 숫자 키'array ("1"=> ​​"1")를 정수로 저장합니다. 그걸 알아 채지 못해. 키가 계속 증가하는 경우에만 검색하여 실제 목록과 인덱싱 된 배열을 구별 할 수 있습니다. – mario

답변

36

바로 kohana 프레임 워크에서 벗어났습니다.

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 (e.g. the keys array looked like {0:0, 1:1...}). 
    return array_keys($keys) !== $keys; 
} 
+3

+1 우아함을 위해 – pedromanoel

+0

정말로 좋은. 나는 여전히 믿음으로 이것을 조금씩 가지고 있습니다 ...하지만 그것은 제 코드에서 작동합니다, 정말 고마워요! –

+1

[5 => 'foo']와 같이 필터링 된 비 연관 배열에서는 실패합니다. – ARW

7

PHP 취급하는 모든 배열의 메시 구조를 사용하는 것을 피하기 위해 찾고 있어요, 그래서이 작업을 수행하는 정확한 방법이 없습니다. 가장 좋은 방법은 다음을 것입니다 저는 믿습니다 :

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

비 순차 배열 인덱스를 고려하지 않은 고유 한 제한에도 불구하고이 솔루션을 게시했습니다. 이 질문은 다음과 같습니다. http://stackoverflow.com/questions/173400/php-arrays-a-good-way-to-check-if-an-array-is-associative-or-sequential 그것은 완벽합니다. –

+0

"non-sequental"은 정렬을 통해 매우 간단하게 해결할 수 있습니다. –

0

아니, 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) 
} 

(가독성 포맷 이상)

0

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

내가 누락 된 것이 있기 때문에 나를 통해 당신의 기능을 걸어보십시오. foreach 루프가 있지만 루프의 첫 번째 반복에서 돌아옵니다! 첫 번째 키가 정수인지 여부를 반환하는 경우 루프의 요점은 무엇입니까? 아마도 플래그를 true로 설정하고 루프가 정수이면 플래그를 false로 설정하겠습니까? –

+0

그렇지 않으면 항상 정수 값을 배열 키로 얻습니다. –

+0

이것은 실제 답변 IMHO에 더 가깝습니다. Tom Auger는 요점이 있습니다. 나는 그것이있을 거라고 생각보다 같은 : 개인 기능 is_hash ($ 배열) { foreach는 (키 $로 array_keys ($ 배열)) { 경우 (is_int ($ 키)) { 반환 거짓; } } return true; } – Garvin

11

This benchmark은 3 가지 방법을 제공한다.

다음은 요약입니다. 은 가장 빠른 것에서 가장 느린 것으로부터 정렬되었습니다.. 자세한 내용은 benchmark here을 읽어보십시오.

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; 
} 
+0

실제 벤치 마크로 주석을 달아 주시면 좋겠습니다. 링크가 부실한 경우에 대비하여 'array_filter' 접근법은 다른 배열보다 __slower__만큼 큰 것입니다. –

관련 문제