目次
回复内容:
ホームページ バックエンド開発 PHPチュートリアル php中如何找出一个哈希数组中的某个元素的前后项

php中如何找出一个哈希数组中的某个元素的前后项

Jun 06, 2016 pm 08:51 PM
php 配列

这个标题看起来比较绕口,我直接上代码吧,比如有下面这样一种形式组织的数组

$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...

我写了段测试代码:

";

$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 '; else echo 'no next key
'; ?>
ログイン後にコピー

null的说的对(已经点了赞了),在php function层面(Zend API层面我不知道),没有办法绕过数组遍历,代码大概像这样(随手写的伪代码,不能执行的,下同):

<?php $a = array(....);
$ele = current($a);
while (FALSE !== $ele)
{
    if (你在找的VALUE(不是 KEY)!==$ele)
    {
        $ele = next($a);
    }
    else
    {
        分别用next(), prev()取出你要的值
        break;
    }
}
ログイン後にコピー

如果你要找的值不是数组倒数第一/二个,不会遍历整个数组。

但这种写法对你的代码能力要求较高,代码量大一些,看起来不直观,你要注意:
1. current()取出来的元素value值恰好是false的时候容易出错,须使用===比较操作符
2. while循环第一轮和最后一轮要特殊处理,因为你要找的值有可能恰好在数组的头尾上,没有prev或者next
3. current,next,prev取出元素值的同时,也移动了数组内部指针,这几个函数比较小众,接手维护的人可能看不懂

采用何志强同学的方案,代码就简洁多了:

<?php $keys = array_key($a);
$mid_number_index = array_search(你在找的KEY(不是VALUE), $keys);

if (0 < $mid_number_index)
{
    $prev_key = $mid_number_index-1;
    $prev_value = $a[$prev_key];
}

if (sizeof($a) > $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_DEBUG
	int 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)的时间来获得你要的答案。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

CakePHP プロジェクトの構成 CakePHP プロジェクトの構成 Sep 10, 2024 pm 05:25 PM

この章では、CakePHP の環境変数、一般設定、データベース設定、電子メール設定について理解します。

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

CakePHP の日付と時刻 CakePHP の日付と時刻 Sep 10, 2024 pm 05:27 PM

Cakephp4 で日付と時刻を操作するには、利用可能な FrozenTime クラスを利用します。

CakePHP ファイルのアップロード CakePHP ファイルのアップロード Sep 10, 2024 pm 05:27 PM

ファイルのアップロードを行うには、フォーム ヘルパーを使用します。ここではファイルアップロードの例を示します。

CakePHP ルーティング CakePHP ルーティング Sep 10, 2024 pm 05:25 PM

この章では、ルーティングに関連する次のトピックを学習します。

CakePHP について話し合う CakePHP について話し合う Sep 10, 2024 pm 05:28 PM

CakePHP は、PHP 用のオープンソース フレームワークです。これは、アプリケーションの開発、展開、保守をより簡単にすることを目的としています。 CakePHP は、強力かつ理解しやすい MVC のようなアーキテクチャに基づいています。モデル、ビュー、コントローラー

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

CakePHP バリデータの作成 CakePHP バリデータの作成 Sep 10, 2024 pm 05:26 PM

Validator は、コントローラーに次の 2 行を追加することで作成できます。

See all articles