PHP将所有数组都视为关联数组,因此没有任何内置函数。谁能推荐一种相当有效的方法来检查数组是否“是一个列表”(只包含从0开始的数字键)?
基本上,我希望能够区分这些:
$sequentialArray = [
'apple', 'orange', 'tomato', 'carrot'
];
这:
$assocArray = [
'fruit1' => 'apple',
'fruit2' => 'orange',
'veg1' => 'tomato',
'veg2' => 'carrot'
];
修改最流行的答案。
这需要更多的处理,但更准确。
<?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
?>
这个问题实际上在php数组中是没有用的,因为php的本质是数组不应该是完全关联的或索引的,它可以是两者的组合,用户定义和赋值数组的方式可以是两者的组合。参见下面的示例
$y= array(5);
$y["0x"]="n";
$y["vbg"]="12132";
$y[1] = "k";
var_dump($y); //this will output 4 element array
echo "</br>" .$y["0x"]."</br>".$y[0];
for($x=0;$x<sizeof($y);$x++){ // this will output all index elements & gives error after that
echo "</br> index elements ".$y[$x];
}
正确的问题是,数组中的所有元素都是关联的还是下标的。如果你真的知道它只能是关联数组或索引数组而不是两者的组合,你可以简单地使用这个方法来确定它是索引数组还是关联数组。
function AssocTest(&$arr){
if(is_array($arr)){
reset($arr); // reset pointer to first element of array
if(gettype(key($arr)) == "string"){ //get the type(nature) of first element key
return true;
}else{
return false;
}
}else{
return false;
}
}
你可以正常使用它
echo(AssocTest($y)? "Associative array": "Not an Associative array/ Not an array at all");
重要的是,evan,你已经初始化了一个关联数组但是你给关联数组的名字只是数字当它被PHP读取时它会被当作一个索引数组如果你没有显式地给字符串名字。看看下面的例子。
$y["0"]="n";
$y["1"]="12132";
$y["22"] = "k";
//both will get the same output
echo "<br/> s0 ".$y["22"];
echo "<br/> s0 ".$y[22];
for($x=0;$x<count($y);$x++){
echo "<br/> arr ".$y[$x]; // this will output up to 2nd element and give an error after
}
如果你需要确保数组中的所有元素都被精确索引,或者是关联的,没有其他方法,只能对所有元素赋真,并检查每个元素键通过生成索引数组,就像这里很多人发布的那样。
function fullAssocTest(&$arr)
{
if(is_array($arr)){
return (array_keys($arr) !== range(0, count($arr) - 1));
}
}
它的代码更少,但这个东西真的是过程密集和真正不必要的工作。
我认为下面两个函数是最好的方法去检查'如果一个数组是结合或数字'。由于'numeric'可能只表示数字键或顺序数字键,下面列出了两个函数来检查这两种情况:
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));
}
The first function checks if each key is an integer value. The second function checks if each key is an integer value and in addition checks if all keys are sequential starting at $base, which defaults to 0 and thus can be omitted if you do not need to specify another base value. key($my_array) returns null if the read pointer is moved past the end of the array, which is what ends the for loop and makes the statement after the for loop return true if all keys were integer. If not, the loop ends prematurely because a key is of type string, and the statement after the for loop will return false. The latter function in addition adds one to $base after each compare, to be able to check if the next key is of the correct value. The strict compare makes it also check if the key is of type integer. The $base = (int) $base part in the first section of the for loop can be left out when $base is omitted or if you make sure it is only called using an integer. But since I can't be sure for everybody, I left it in. The statement is executed only once, anyway. I think these are the most efficient solutions:
Memory wise: No copying of data or key ranges. Doing an array_values or array_keys may seem shorter (less code) but keep in mind what goes on in the background once you make that call. Yes there are more (visible) statements than in some other solutions, but that is not what counts, is it?
Time wise: Besides the fact that copying/extracting data and/or keys also takes time, this solution is more efficient than doing a foreach. Again a foreach may seem more efficient to some because it is shorter in notation, but in the background foreach also calls reset, key and next to do it's looping. But in addition it also calls valid to check the end condition, which is avoided here due to the combination with the integer check.
请记住,数组键只能是整数或字符串,严格的数字字符串,如“1”(但不是“01”)将被转换为整数。如果您希望数组是顺序的,这使得检查整数键成为除了计数之外唯一需要的操作。当然,如果is_indexed_array返回false,则可以将该数组视为关联数组。我说“见过”,因为事实上它们都是。