PHP基礎(chǔ)之?dāng)?shù)據(jù)類型5——數(shù)組(Array)
PHP 中的數(shù)組實際上是一個有序映射。映射是一種把 values 關(guān)聯(lián)到 keys 的類型。此類型在很多方面做了優(yōu)化,因此可以把它當(dāng)成真正的數(shù)組,或列表(向量),散列表(是映射的一種實現(xiàn)),字典,集合,棧,隊列以及更多可能性。由于數(shù)組元素的值也可以是另一個數(shù)組,樹形結(jié)構(gòu)和多維數(shù)組也是允許的。
解釋這些結(jié)構(gòu)超出了本手冊的范圍,但對于每種結(jié)構(gòu)至少會提供一個例子。要得到這些結(jié)構(gòu)的更多信息,建議參考有關(guān)此廣闊主題的其它著作。
語法定義數(shù)組 array()可以用 array() 語言結(jié)構(gòu)來新建一個數(shù)組。它接受任意數(shù)量用逗號分隔的 鍵(key) => 值(value)對。
array( key => value, ...)// 鍵(key)可是是一個整數(shù) integer 或字符串 string// 值(value)可以是任意類型的值
最后一個數(shù)組單元之后的逗號可以省略。通常用于單行數(shù)組定義中,例如常用 array(1, 2) 而不是 array(1, 2, )。對多行數(shù)組定義通常保留最后一個逗號,這樣要添加一個新單元時更方便。
自 5.4 起可以使用短數(shù)組定義語法,用 [] 替代 array()。
Example #1 一個簡單數(shù)組
<?php
$array = array(
???'foo' => 'bar',
???'bar' => 'foo',
);
// 自 PHP 5.4 起
$array = [
???'foo' => 'bar',
???'bar' => 'foo',
];
?>
key 可以是 integer 或者 string。value 可以是任意類型。
此外 key 會有如下的強制轉(zhuǎn)換:
包含有合法整型值的字符串會被轉(zhuǎn)換為整型。例如鍵名 '8' 實際會被儲存為 8。但是 '08' 則不會強制轉(zhuǎn)換,因為其不是一個合法的十進制數(shù)值。
浮點數(shù)也會被轉(zhuǎn)換為整型,意味著其小數(shù)部分會被舍去。例如鍵名 8.7 實際會被儲存為 8。
布爾值也會被轉(zhuǎn)換成整型。即鍵名 true 實際會被儲存為 1 而鍵名 false 會被儲存為 0。
Null 會被轉(zhuǎn)換為空字符串,即鍵名 null 實際會被儲存為 ''。
數(shù)組和對象不能被用為鍵名。堅持這么做會導(dǎo)致警告:Illegal offset type。
如果在數(shù)組定義中多個單元都使用了同一個鍵名,則只使用了最后一個,之前的都被覆蓋了。
Example #2 類型強制與覆蓋示例
<?php
$array = array(
???1 ???=> 'a',
???'1' ?=> 'b',
???1.5 ?=> 'c',
???true => 'd',
);
var_dump($array);
?>
以上例程會輸出:
array(1) {[1]=>string(1) 'd'}
上例中所有的鍵名都被強制轉(zhuǎn)換為 1,則每一個新單元都會覆蓋前一個的值,最后剩下的只有一個 'd'。
PHP 數(shù)組可以同時含有 integer 和 string 類型的鍵名,因為 PHP 實際并不區(qū)分索引數(shù)組和關(guān)聯(lián)數(shù)組。
如果對給出的值沒有指定鍵名,則取當(dāng)前最大的整數(shù)索引值,而新的鍵名將是該值加一。如果指定的鍵名已經(jīng)有了值,則該值會被覆蓋。
Example #3 混合 integer 和 string 鍵名
<?php
$array = array(
???'foo' => 'bar',
???'bar' => 'foo',
???100 ??=> -100,
???-100 ?=> 100,
);
var_dump($array);
?>
以上例程會輸出:
array(4) {['foo']=>string(3) 'bar'['bar']=>string(3) 'foo'[100]=>int(-100)[-100]=>int(100)}
key 為可選項。如果未指定,PHP 將自動使用之前用過的最大 integer 鍵名加上 1 作為新的鍵名。
Example #4 沒有鍵名的索引數(shù)組
<?php
$array = array('foo', 'bar', 'hallo', 'world');
var_dump($array);
?>
以上例程會輸出:
array(4) {[0]=>string(3) 'foo'[1]=>string(3) 'bar'[2]=>string(5) 'hallo'[3]=>string(5) 'world'}
還可以只對某些單元指定鍵名而對其它的空置:
Example #5 僅對部分單元指定鍵名
<?php
$array = array(
????????'a',
????????'b',
???6 => 'c',
????????'d',
);
var_dump($array);
?>
以上例程會輸出:
array(4) {[0]=>string(1) 'a'[1]=>string(1) 'b'[6]=>string(1) 'c'[7]=>string(1) 'd'}
可以看到最后一個值 'd' 被自動賦予了鍵名 7。這是由于之前最大的整數(shù)鍵名是 6。
用方括號語法訪問數(shù)組單元數(shù)組單元可以通過 array[key] 語法來訪問。
Example #6 訪問數(shù)組單元
<?php
$array = array(
???'foo' => 'bar',
???42 ???=> 24,
???'multi' => array(
????????'dimensional' => array(
????????????'array' => 'foo'
????????)
???)
);
var_dump($array['foo']);
var_dump($array[42]);
var_dump($array['multi']['dimensional']['array']);
?>
以上例程會輸出:
string(3) 'bar'int(24)string(3) 'foo'
Note:
方括號和花括號可以互換使用來訪問數(shù)組單元(例如 $array[42] 和 $array{42} 在上例中效果相同)。
自 PHP 5.4 起可以用數(shù)組間接引用函數(shù)或方法調(diào)用的結(jié)果。之前只能通過一個臨時變量。
自 PHP 5.5 起可以用數(shù)組間接引用一個數(shù)組原型。
Example #7 數(shù)組間接引用
<?php
function getArray() {
???return array(1, 2, 3);
}
// on PHP 5.4
$secondElement = getArray()[1];
// previously
$tmp = getArray();
$secondElement = $tmp[1];
// or
list(, $secondElement) = getArray();
?>
Note:
試圖訪問一個未定義的數(shù)組鍵名與訪問任何未定義變量一樣:會導(dǎo)致 E_NOTICE 級別錯誤信息,其結(jié)果為 NULL。
用方括號的語法新建/修改可以通過明示地設(shè)定其中的值來修改一個已有數(shù)組。
這是通過在方括號內(nèi)指定鍵名來給數(shù)組賦值實現(xiàn)的。也可以省略鍵名,在這種情況下給變量名加上一對空的方括號([])。
$arr[key] = value;$arr[] = value;// key 可以是 integer 或 string// value 可以是任意類型的值
如果 $arr 還不存在,將會新建一個,這也是另一種新建數(shù)組的方法。不過并不鼓勵這樣做,因為如果 $arr 已經(jīng)包含有值(例如來自請求變量的 string)則此值會保留而 [] 實際上代表著字符串訪問運算符。初始化變量的最好方式是直接給其賦值。。
要修改某個值,通過其鍵名給該單元賦一個新值。要刪除某鍵值對,對其調(diào)用 unset() 函數(shù)。
<?php
$arr = array(5 => 1, 12 => 2);
$arr[] = 56; ???// This is the same as $arr[13] = 56;
???????????????// at this point of the script
$arr['x'] = 42; // This adds a new element to
???????????????// the array with key 'x'
unset($arr[5]); // This removes the element from the array
unset($arr); ???// This deletes the whole array
?>
Note:
如上所述,如果給出方括號但沒有指定鍵名,則取當(dāng)前最大整數(shù)索引值,新的鍵名將是該值加上 1(但是最小為 0)。如果當(dāng)前還沒有整數(shù)索引,則鍵名將為 0。
注意這里所使用的最大整數(shù)鍵名不一定當(dāng)前就在數(shù)組中。它只要在上次數(shù)組重新生成索引后曾經(jīng)存在過就行了。以下面的例子來說明:
<?php
// 創(chuàng)建一個簡單的數(shù)組
$array = array(1, 2, 3, 4, 5);
print_r($array);
// 現(xiàn)在刪除其中的所有元素,但保持?jǐn)?shù)組本身不變:
foreach ($array as $i => $value) {
???unset($array[$i]);
}
print_r($array);
// 添加一個單元(注意新的鍵名是 5,而不是你可能以為的 0)
$array[] = 6;
print_r($array);
// 重新索引:
$array = array_values($array);
$array[] = 7;
print_r($array);
?>
以上例程會輸出:
Array([0] => 1[1] => 2[2] => 3[3] => 4[4] => 5)Array()Array([5] => 6)Array([0] => 6[1] => 7)
實用函數(shù)有很多操作數(shù)組的函數(shù),參見數(shù)組函數(shù)一節(jié)。
Note:
unset() 函數(shù)允許刪除數(shù)組中的某個鍵。但要注意數(shù)組將不會重建索引。如果需要刪除后重建索引,可以用 array_values() 函數(shù)。
<?php
$a = array(1 => ’one’, 2 => ’two’, 3 => ’three’);
unset($a[2]);
/* will produce an array that would have been defined as
??$a = array(1 => ’one’, 3 => ’three’);
??and NOT
??$a = array(1 => ’one’, 2 =>’three’);
*/
$b = array_values($a);
// Now $b is array(0 => ’one’, 1 =>’three’)
?>
foreach 控制結(jié)構(gòu)是專門用于數(shù)組的。它提供了一個簡單的方法來遍歷數(shù)組。
數(shù)組做什么和不做什么為什么 $foo[bar] 錯了?應(yīng)該始終在用字符串表示的數(shù)組索引上加上引號。例如用 $foo[’bar’] 而不是 $foo[bar]。但是為什么呢?可能在老的腳本中見過如下語法:
<?php
$foo[bar] = ’enemy’;
echo $foo[bar];
// etc
?>
這樣是錯的,但可以正常運行。那么為什么錯了呢?原因是此代碼中有一個未定義的常量(bar)而不是字符串(’bar’-注意引號),而 PHP 可能會在以后定義此常量,不幸的是你的代碼中有同樣的名字。它能運行,是因為 PHP 自動將裸字符串(沒有引號的字符串且不對應(yīng)于任何已知符號)轉(zhuǎn)換成一個其值為該裸字符串的正常字符串。例如,如果沒有常量定義為 bar,PHP 將把它替代為 ’bar’ 并使用之。
Note: 這并不意味著總是給鍵名加上引號。用不著給鍵名為常量或變量的加上引號,否則會使 PHP 不能解析它們。
<?php
error_reporting(E_ALL);
ini_set(’display_errors’, true);
ini_set(’html_errors’, false);
// Simple array:
$array = array(1, 2);
$count = count($array);
for ($i = 0; $i < $count; $i++) {
???echo 'nChecking $i: n';
???echo 'Bad: ' . $array[’$i’] . 'n';
???echo 'Good: ' . $array[$i] . 'n';
???echo 'Bad: {$array[’$i’]}n';
???echo 'Good: {$array[$i]}n';
}
?>
以上例程會輸出:
Checking 0:Notice: Undefined index: ?$i in /path/to/script.html on line 9Bad:Good: 1Notice: Undefined index: ?$i in /path/to/script.html on line 11Bad:Good: 1
Checking 1:Notice: Undefined index: ?$i in /path/to/script.html on line 9Bad:Good: 2Notice: Undefined index: ?$i in /path/to/script.html on line 11Bad:Good: 2
演示此行為的更多例子:
<?php
// Show all errors
error_reporting(E_ALL);
$arr = array(’fruit’ => ’apple’, ’veggie’ => ’carrot’);
// Correct
print $arr[’fruit’]; ?// apple
print $arr[’veggie’]; // carrot
// Incorrect. ?This works but also throws a PHP error of level E_NOTICE because
// of an undefined constant named fruit
//
// Notice: Use of undefined constant fruit - assumed ’fruit’ in...
print $arr[fruit]; ???// apple
// This defines a constant to demonstrate what’s going on. ?The value ’veggie’
// is assigned to a constant named fruit.
define(’fruit’, ’veggie’);
// Notice the difference now
print $arr[’fruit’]; ?// apple
print $arr[fruit]; ???// carrot
// The following is okay, as it’s inside a string. Constants are not looked for
// within strings, so no E_NOTICE occurs here
print 'Hello $arr[fruit]'; ?????// Hello apple
// With one exception: braces surrounding arrays within strings allows constants
// to be interpreted
print 'Hello {$arr[fruit]}'; ???// Hello carrot
print 'Hello {$arr[’fruit’]}'; ?// Hello apple
// This will not work, and will result in a parse error, such as:
// Parse error: parse error, expecting T_STRING’ or T_VARIABLE’ or T_NUM_STRING’
// This of course applies to using superglobals in strings as well
print 'Hello $arr[’fruit’]';
print 'Hello $_GET[’foo’]';
// Concatenation is another option
print 'Hello ' . $arr[’fruit’]; // Hello apple
?>
當(dāng)打開 error_reporting 來顯示 E_NOTICE 級別的錯誤(將其設(shè)為 E_ALL)時將看到這些錯誤。默認(rèn)情況下 error_reporting 被關(guān)閉不顯示這些。
和在語法一節(jié)中規(guī)定的一樣,在方括號(“[”和“]”)之間必須有一個表達式。這意味著可以這樣寫:
<?php
echo $arr[somefunc($bar)];
?>
這是一個用函數(shù)返回值作為數(shù)組索引的例子。PHP 也可以用已知常量,可能之前已經(jīng)見過:
<?php
$error_descriptions[E_ERROR] ??= 'A fatal error has occured';
$error_descriptions[E_WARNING] = 'PHP issued a warning';
$error_descriptions[E_NOTICE] ?= 'This is just an informal notice';
?>
注意 E_ERROR 也是個合法的標(biāo)識符,就和第一個例子中的 bar 一樣。但是上一個例子實際上和如下寫法是一樣的:
<?php
$error_descriptions[1] = 'A fatal error has occured';
$error_descriptions[2] = 'PHP issued a warning';
$error_descriptions[8] = 'This is just an informal notice';
?>
因為 E_ERROR 等于 1,等等。
那么為什么這樣做不好?也許有一天,PHP 開發(fā)小組可能會想新增一個常量或者關(guān)鍵字,或者用戶可能希望以后在自己的程序中引入新的常量,那就有麻煩了。例如已經(jīng)不能這樣用 empty 和 default 這兩個詞了,因為他們是保留字。
Note: 重申一次,在雙引號字符串中,不給索引加上引號是合法的因此 '$foo[bar]' 是合法的(“合法”的原文為 valid。在實際測試中,這么做確實可以訪問數(shù)組的該元素,但是會報一個常量未定義的 notice。無論如何,強烈建議不要使用 $foo[bar]這樣的寫法,而要使用 $foo[’bar’] 來訪問數(shù)組中元素。--haohappy 注)。至于為什么參見以上的例子和字符串中的變量解析中的解釋。
轉(zhuǎn)換為數(shù)組對于任意 integer,float,string,boolean 和 resource 類型,如果將一個值轉(zhuǎn)換為數(shù)組,將得到一個僅有一個元素的數(shù)組,其下標(biāo)為 0,該元素即為此標(biāo)量的值。換句話說,(array)$scalarValue 與 array($scalarValue) 完全一樣。
如果一個 object 類型轉(zhuǎn)換為 array,則結(jié)果為一個數(shù)組,其單元為該對象的屬性。鍵名將為成員變量名,不過有幾點例外:整數(shù)屬性不可訪問;私有變量前會加上類名作前綴;保護變量前會加上一個 ’*’ 做前綴。這些前綴的前后都各有一個 NULL 字符。這會導(dǎo)致一些不可預(yù)知的行為:
<?php
class A {
???private $A; // This will become ’0A0A’
}
class B extends A {
???private $A; // This will become ’0B0A’
???public $AA; // This will become ’AA’
}
var_dump((array) new B());
?>
上例會有兩個鍵名為 ’AA’,不過其中一個實際上是 ’0A0A’。
將 NULL 轉(zhuǎn)換為 array 會得到一個空的數(shù)組。
比較可以用 array_diff() 和數(shù)組運算符來比較數(shù)組。
示例PHP 中的數(shù)組類型有非常多的用途。以下是一些示例:
<?php
// This:
$a = array( ’color’ => ’red’,
???????????’taste’ => ’sweet’,
???????????’shape’ => ’round’,
???????????’name’ ?=> ’apple’,
???????????4 ???????// key will be 0
?????????);
$b = array(’a’, ’b’, ’c’);
// . . .is completely equivalent with this:
$a = array();
$a[’color’] = ’red’;
$a[’taste’] = ’sweet’;
$a[’shape’] = ’round’;
$a[’name’] ?= ’apple’;
$a[] ???????= 4; ???????// key will be 0
$b = array();
$b[] = ’a’;
$b[] = ’b’;
$b[] = ’c’;
// After the above code is executed, $a will be the array
// array(’color’ => ’red’, ’taste’ => ’sweet’, ’shape’ => ’round’,
// ’name’ => ’apple’, 0 => 4), and $b will be the array
// array(0 => ’a’, 1 => ’b’, 2 => ’c’), or simply array(’a’, ’b’, ’c’).
?>
Example #8 使用 array()
<?php
// Array as (property-)map
$map = array( ’version’ ???=> 4,
?????????????’OS’ ????????=> ’Linux’,
?????????????’lang’ ??????=> ’english’,
?????????????’short_tags’ => true
???????????);
// strictly numerical keys
$array = array( 7,
???????????????8,
???????????????0,
???????????????156,
???????????????-10
?????????????);
// this is the same as array(0 => 7, 1 => 8, ...)
$switching = array( ????????10, // key = 0
???????????????????5 ???=> ?6,
???????????????????3 ???=> ?7,
???????????????????’a’ ?=> ?4,
???????????????????????????11, // key = 6 (maximum of integer-indices was 5)
???????????????????’8’ ?=> ?2, // key = 8 (integer!)
???????????????????’02’ => 77, // key = ’02’
???????????????????0 ???=> 12 ?// the value 10 will be overwritten by 12
?????????????????);
// empty array
$empty = array();
?>
Example #9 集合
<?php
$colors = array(’red’, ’blue’, ’green’, ’yellow’);
foreach ($colors as $color) {
???echo 'Do you like $color?n';
}
?>
以上例程會輸出:
Do you like red?Do you like blue?Do you like green?Do you like yellow?
直接改變數(shù)組的值自 PHP 5 起可以通過引用傳遞來做到。之前的版本需要需要采取變通的方法:
Example #10 在循環(huán)中改變單元
<?php
// PHP 5
foreach ($colors as &$color) {
???$color = strtoupper($color);
}
unset($color); /* ensure that following writes to
$color will not modify the last array element */
// Workaround for older versions
foreach ($colors as $key => $color) {
???$colors[$key] = strtoupper($color);
}
print_r($colors);
?>
以上例程會輸出:
Array([0] => RED[1] => BLUE[2] => GREEN[3] => YELLOW)
本例生成一個下標(biāo)從 1 開始的數(shù)組。
Example #11 下標(biāo)從 1 開始的數(shù)組
<?php
$firstquarter ?= array(1 => ’January’, ’February’, ’March’);
print_r($firstquarter);
?>
以上例程會輸出:
Array([1] => ’January’[2] => ’February’[3] => ’March’)
Example #12 填充數(shù)組
<?php
// fill an array with all items from a directory
$handle = opendir(’.’);
while (false !== ($file = readdir($handle))) {
???$files[] = $file;
}
closedir($handle);
?>
數(shù)組是有序的。也可以使用不同的排序函數(shù)來改變順序。更多信息參見數(shù)組函數(shù)。可以用 count() 函數(shù)來數(shù)出數(shù)組中元素的個數(shù)。
Example #13 數(shù)組排序
<?php
sort($files);
print_r($files);
?>
因為數(shù)組中的值可以為任意值,也可是另一個數(shù)組。這樣可以產(chǎn)生遞歸或多維數(shù)組。
Example #14 遞歸和多維數(shù)組
<?php
$fruits = array ( 'fruits' ?=> array ( 'a' => 'orange',
??????????????????????????????????????'b' => 'banana',
??????????????????????????????????????'c' => 'apple'
????????????????????????????????????),
?????????????????'numbers' => array ( 1,
??????????????????????????????????????2,
??????????????????????????????????????3,
??????????????????????????????????????4,
??????????????????????????????????????5,
??????????????????????????????????????6
????????????????????????????????????),
?????????????????'holes' ??=> array ( ?????'first',
??????????????????????????????????????5 => 'second',
???????????????????????????????????????????'third'
????????????????????????????????????)
???????????????);
// Some examples to address values in the array above
echo $fruits['holes'][5]; ???// prints 'second'
echo $fruits['fruits']['a']; // prints 'orange'
unset($fruits['holes'][0]); ?// remove 'first'
// Create a new multi-dimensional array
$juices['apple']['green'] = 'good';
?>
數(shù)組(Array) 的賦值總是會涉及到值的拷貝。使用引用運算符通過引用來拷貝數(shù)組。
<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
????????????// $arr1 is still array(2, 3)
$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>
相關(guān)文章:
