php中如何找出一個雜湊數組中的某個元素的前後項

來源:互聯網
上載者:User
這個標題看起來比較繞口,我直接上代碼吧,比如有下面這樣一種形式組織的數組

$a = array(    'key12'    =>    12323,    'key32'    =>    4345,    'key13'    =>    323423,    'key43'    =>    32423,    'key25'    =>    33423);

對於一個未知的數組,我知道了其中任意一個已經存在的元素的索引值,比如就是key13吧,那我如何知道key13的前後分別是哪兩個鍵呢?比如在這個例子中,我如何才能知道$akey13,找出key32key43呢?

這種雜湊數組沒有順序的數值索引值,因此不能對索引值+1或者-1,來擷取前驅和後繼,不知道各位有什麼好辦法?

回複內容:

這個標題看起來比較繞口,我直接上代碼吧,比如有下面這樣一種形式組織的數組

$a = array(    'key12'    =>    12323,    'key32'    =>    4345,    'key13'    =>    323423,    'key43'    =>    32423,    'key25'    =>    33423);

對於一個未知的數組,我知道了其中任意一個已經存在的元素的索引值,比如就是key13吧,那我如何知道key13的前後分別是哪兩個鍵呢?比如在這個例子中,我如何才能知道$akey13,找出key32key43呢?

這種雜湊數組沒有順序的數值索引值,因此不能對索引值+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)的時間來獲得你要的答案。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.