這個標題看起來比較繞口,我直接上代碼吧,比如有下面這樣一種形式組織的數組
$a = array( 'key12' => 12323, 'key32' => 4345, 'key13' => 323423, 'key43' => 32423, 'key25' => 33423);
對於一個未知的數組,我知道了其中任意一個已經存在的元素的索引值,比如就是key13吧,那我如何知道key13的前後分別是哪兩個鍵呢?比如在這個例子中,我如何才能知道$a和key13,找出key32和key43呢?
這種雜湊數組沒有順序的數值索引值,因此不能對索引值+1或者-1,來擷取前驅和後繼,不知道各位有什麼好辦法?
回複內容:
這個標題看起來比較繞口,我直接上代碼吧,比如有下面這樣一種形式組織的數組
$a = array( 'key12' => 12323, 'key32' => 4345, 'key13' => 323423, 'key43' => 32423, 'key25' => 33423);
對於一個未知的數組,我知道了其中任意一個已經存在的元素的索引值,比如就是key13吧,那我如何知道key13的前後分別是哪兩個鍵呢?比如在這個例子中,我如何才能知道$a和key13,找出key32和key43呢?
這種雜湊數組沒有順序的數值索引值,因此不能對索引值+1或者-1,來擷取前驅和後繼,不知道各位有什麼好辦法?
可以參考下php - Search array keys and return the index of matched key - Stack Overflow,思路是找出key所在的索引,然後根據索引再減1或加1取得前後項:http://stackoverflow.com/questions/37...
我寫了段測試代碼:
12323, 'key32' => 4345, 'key13' => 323423, 'key43' => 32423, 'key25' => 33423);print_r($a);echo "
";$key = 'key13';// 尋找key的索引號$keys = array_keys($a);$key_index = array_search($key, $keys);echo "index of $key is $key_index
";// 將key索引號減1或加1取得前項和後項索引(注意要判斷是否越界)if ($key_index == 0) echo 'no pre key
';else echo 'pre key is ' . $keys[$key_index - 1] . '
';if ($key_index < count($keys)) echo 'next key is ' . $keys[$key_index + 1] . '
';else echo 'no next key
';?>
null的說的對(已經點了贊了),在php function層面(Zend API層面我不知道),沒有辦法繞過數組遍曆,代碼大概像這樣(隨手寫的虛擬碼,不能執行的,下同):
如果你要找的值不是數組倒數第一/二個,不會遍曆整個數組。
但這種寫法對你的代碼能力要求較高,代碼量大一些,看起來不直觀,你要注意:
1. current()取出來的元素value值恰好是false的時候容易出錯,須使用===比較操作符
2. while迴圈第一輪和最後一輪要特殊處理,因為你要找的值有可能恰好在數組的頭尾上,沒有prev或者next
3. current,next,prev取出元素值的同時,也移動了數組內部指標,這幾個函數比較小眾,接手維護的人可能看不懂
採用何志強同學的方案,代碼就簡潔多了:
$mid_number_index){ $next_key = $mid_number_index+1; $next_value = $a[$next_key];}很顯然,這個方案有兩個效能稍差的地方:
1.array_keys()一定要遍曆全部數組元素
2.array_search()搜尋時還要遍曆(但中途找到就break了)
如果你的數組不是很大,推薦用何志強同學的方案寫代碼。
php 的array 是hash+雙向鏈表的結構實現的. 參考php 源碼: Zend/zend_hash.h
typedef struct _hashtable {uint nTableSize;uint nTableMask;uint nNumOfElements;ulong nNextFreeElement;Bucket *pInternalPointer;/* Used for element traversal */Bucket *pListHead;Bucket *pListTail;Bucket **arBuckets;dtor_func_t pDestructor;zend_bool persistent;unsigned char nApplyCount;zend_bool bApplyProtection;#if ZEND_DEBUGint inconsistent;#endif} HashTable;其中pInternalPointer 就是數組的內部指標. 如果內部指標指向位置ok,可以擷取鏈表的前後項目指標. 但目前沒有發現 php 提供根據 key 來設定 array 的 internal pointer 的外部函數. 所以線性遍曆不可避免了.
看到有一種相對簡潔的方法:
$a = array( 'key12' => 12323, 'key32' => 4345, 'key13' => 323423, 'key43' => 32423, 'key25' => 33423);while(key($a) !== 'key13') next($a);$prev_val = prev($array);# 前一項的value$prev_key = key($array);# 前一項的key
擷取後一項用 next 函數, 方法類似.
參考: http://stackoverflow.com/questions/47...
遍曆數組再通過prev/next這些函數操作, 或者提取keys組成新數組,然後通過value(原先的key值)取數字下標,再對應key
大體除了這些好像沒太好的辦法
樓上提到的方法都需要把整個數組過一遍,效率比較低,限於語言層面的原因,只使用php語言本身也只能達到這個程度。
但是正如 @liruqi 同學的答案,PHP實際上是使用了HASH+雙向鏈表的方式來實現的,所以如果給PHP寫一個C擴充的話,可以用O(1)的時間來獲得你要的答案。