2011-05-13 125 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 

即:該函數的一些不同的東西,當它「檢測」這是傳遞一個哈希,而不是一個數組。你能否告訴我來自Perl背景,其中%哈希是來自@arrays的不同引用?

我相信我的例子很重要,因爲我們不能僅僅測試一下鍵是否是數字,因爲你可以在你的散列中使用數字鍵。

我專門找避免使用的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 – 2011-05-13 19:30:09

+0

有趣的問題。很遺憾,PHP不會區分array('a','b','c')和array(0 =>'a',1 =>'b',2 =>'c')...... – Tadeck 2011-05-13 19:31:41

+1

PHP將始終將數組鍵(「1」=>「1」)作爲整數存儲。無法檢測到。您只能探測不斷增長的密鑰,才能將真正的列表與索引數組區分開來。 – mario 2011-05-13 19:35:49

回答

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 2013-07-03 19:43:42

+0

確實很不錯。我仍然堅信這一點信仰......但它在我的代碼中起作用,所以謝謝! – 2013-12-17 16:05:03

+1

對於已過濾的非關聯數組,如[5 =>'foo'],這會失敗。 – ARW 2015-07-11 23:12:41

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有更多的解決方案,沒有這是完美的。 – 2011-06-15 13:27:41

+0

「非sequental」可以通過排序非常簡單地解決。 – 2011-06-15 13:39:50

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

是錯誤的獲得中hash數組的array_keys象下面這樣:

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

將輸出:

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

因此,將它與最高評分答案中提到的一系列數字進行比較並不是一個好主意。它總是會說,如果你試圖比較鍵和範圍,它就是一個散列數組。

+0

通過你的功能走過我,因爲有一些我錯過了。你有一個foreach循環,但是你在循環的第一個迭代中返回!如果你只是返回第一個鍵是一個整數,循環的重點是什麼?也許你打算設置一個標誌爲true,然後在我們的循環中,如果它是一個整數,將標誌設置爲false? – 2011-12-20 14:24:29

+0

否則你總是得到一個整數值作爲數組鍵這就是爲什麼! – 2011-12-27 07:42:44

+0

這更接近真正的答案恕我直言。儘管湯姆奧格有一個觀點。我認爲它會更類似於: private function is_hash($ array)foreach(array_keys($ array)as $ key){ if(is_int($ key)){ return false; } } return true; } – Garvin 2017-02-27 20:45:10

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__非常重要。 – 2015-03-04 21:42:41

相關問題