0

私は次のコードを持っています:

$json = json_decode(URL, true);
foreach($json as $var)
{
    if($var[id] == $valdefined)
    {
        $number = $var[count];
    }
}

json を使用すると、次のようになります。

 [{"id":"1","count":"77937"},
 {"id":"2","count":"20"},
 {"id":"4","count":"25"},
 {"id":"5","count":"11365"}]

これは、jsondecode 後の配列 ($json) の外観です。

 Array ( [0] => Array ( [id] => 1 [count] => 77937 ) [1] => Array ( [id] => 2 [count] => 20 ) [2] => Array ( [id] => 4 [count] => 25 ) [3] => Array ( [id] => 5 [count] => 11365) )

たとえば、$json[id] = 3 の $json[count] とは何かを言う方法はありますか

4

3 に答える 3

0

最初の質問に対する短い答え:なぜ書けないのです$json['count'] where $json['id'] = 3か? PHP はクエリ言語ではないからです。質問を作成する方法は、単純な SQL 選択クエリのように見えます。SQL はそのインデックスをトラバースし、(必要に応じて)テーブル全体のスキャン実行します。SQL の構造化クエリ言語を使用すると、DB実行するループをわざわざ書き出す必要がなくなります。 ループを書いていないからループがないというわけではありません (証拠の欠如は不在の証拠ではありません)。
)。すべてをチューリングするつもりはありませんが、マシン レベルでできることは限られています。下位レベルでは、一度に 1 つずつ実行する必要があります。多くの場合、これはインクリメント、チェック、そして再びインクリメントすることを意味します...別名再帰とトラバース。
PHP は、が意味することを理解していると考え、実際には取得したいのに、が参照する値をarrayで$json['id']返すことを意味していると考えます。を決定するには、ある種のループを作成する必要があります。配列のソートを提案する人もいます。それも、マップ/フィルター/マージする他の関数と同様に、配列全体をループすることを意味します。仕方がない_id$json$json[n]['id']narray_*そのあたり。必要なことを正確に実行するすぐに使用できるコア関数はないため、ループを自分で作成する必要があります。
パフォーマンスが重要な場合は、より効率的なループを作成できます。以下に、わずかに少ないブルート ループである半補間検索を示します。ここでも三分探索を使用できます。それを実装することは、あなたが取り組むことができるものです。

for ($i = 1, $j = count($bar), $h = round($j/2);$i<$j;$i+= $h)
{
    if ($bar[++$i]->id === $search || $bar[--$i]->id === $search || $bar[--$i]->id === $search)
    {//thans to short-circuit evaluation, we can check 3 offsets in one go
        $found = $bar[$i];
        break;
    }//++$i, --$i, --$i ==> $i === $i -1, increment again:
    if ($bar[++$i]->id > $search)
    {// too far
        $i -= $h;//return to previous offset, step will be halved
    }
    else
    {//not far enough
        $h = $j - $i;//set step the remaining length, will be halved
    }
    $h = round($h/2);//halve step, and round, in case $h%2 === 1
    //optional:
    if(($i + $h + 1) === $j)
    {//avoid overflow
       $h -= 1;
    }
}

$barjson でデコードされた配列はどこにありますか。
これがどのように正確に機能するかは、このアプローチの欠点と同様に以下に説明されていますが、今のところ、あなたの質問にもっと関連しています:実装方法:

function lookup(array $arr, $p, $val)
{
    $j = count($arr);
    if ($arr[$j-1]->{$p} < $val)
    {//highest id is still less value is still less than $val:
        return (object) array($p => $val, 'count' => 0, 'error' => 'out of bounds');
    }
    if ($arr[$j-1]->{$p} === $val)
    {//the last element is the one we're looking for?
        return $end;
    }
    if ($arr[0]->{$p} > $val)
    {//the lowest value is still higher than the requested value?
        return (object) array($p => $val, 'count' => 0, 'error' => 'underflow');
    }
    for ($i = 1, $h = round($j/2);$i<$j;$i+= $h)
    {
        if ($arr[++$i]->{$p} === $val || $arr[--$i]->{$p} === $val || $arr[--$i]->{$p} === $val)
        {//checks offsets 2, 1, 0 respectively on first iteration
            return $arr[$i];
        }
        if ($arr[$i++]->{$p} < $val && $arr[$i]->{$p} > $val)
        {//requested value is in between? don't bother, it won't exist, then
            return (object)array($p => $val, 'count' => 0, 'error' => 'does not exist');
        }
        if ($arr[++$i]->{$p} > $val)
        {
            $i -= $h;
        }
        else
        {
            $h = ($j - $i);
        }
        $h = round($h/2);
    }
}
$count = lookup($json, 'id', 3);
echo $count['count'];
//or if you have the latest version of php
$count = (lookup($json, 'id', 3))['count'];//you'll have to return default value for this one

個人的には、プロパティと値のペアが見つからない場合は default-object を返さず、 を返すnullかスローRuntimeExceptionしますが、それはあなたが決めることです。


ループは基本的に次のように機能します。

  1. $i各反復で、オフセット$i+1およびのオブジェクト$i-1がチェックされます。
    オブジェクトが見つかった場合、そのオブジェクトへの参照が割り当てられ$found、ループが終了します
  2. オブジェクトが見つかりません。次の 2 つの手順のいずれかを実行します。
    • オフセットの ID が探しているものより大きい場合、$hオフセットからステップ ( ) を減算し$i、ステップを半分にします。もう一度ループする
    • ID が検索よりも小さい (まだ完了していません): step を配列の残りの長さの半分に変更します。

これがより「賢い」ループ方法である理由を図で示します。

|==========x=============================|//suppose x is what we need, offset 11 of a total length 40:

//iteration 1:
 012 //checked offsets, not found
|==========x=============================|
//offset + 40/2 == 21
//iteration 2:
                     012//offsets 20, 21 and 22, not found, too far
|==========x=============================|
//offset - 21 + round(21/2)~>11 === 12
//iteration 3:
           123 //checks offsets 11, 12, 13) ==> FOUND
|==========x=============================|
assign offset-1
break;

11 回の反復ではなく、わずか 3 回の反復で必要なオブジェクトを見つけることができました。このループはいくらかコストがかかりますが (より多くの計算が必要になります)、欠点が利点を上回ることはめったにありません。
ただし、このループにはいくつかの盲点があるため、まれに速度が遅くなりますが、平均するとかなりうまく機能します。100,000 個のオブジェクトを含む配列を使用して id を探し、このループを数回テストしましたがrandom(1,99999)、平均して .0018ms を管理し、.08ms を超える時間はかかりませんでした。これはまったく悪くありません。
もちろん、オフセットの id と検索された id の差を使用してループを改善するか、オフセット$iの id が検索値とオフセットの id より大きい場合は中断できます。$i-1無限ループを避けるため、検索値よりも小さくなっています。ただし、全体として、これはここで提供されている最もスケーラブルでパフォーマンスの高いループアップ アルゴリズムです。

ここで動作中の基本的なコードパッドを確認してください

関数にループがラップされたコードパッド

于 2013-08-13T12:39:47.353 に答える
0

より良い方法についてはわかりませんが、JSON オブジェクトが大きくなければ、これでも問題ありません。JSONをループするとき、phpはかなり高速です。オブジェクトが巨大な場合は、分割することをお勧めします。私が個人的に行っているのは、JSON を通常のオブジェクトの配列にし、それらを並べ替えて、並べ替えられたアイテムの検索を高速化することです。

編集

json_decode($your_thing, true);true に設定して連想配列にすると、id がkeyになり、count がvalueになります。これを行うと、ID を使用して値を取得するのが非常に簡単になり、はるかに効率的になります。

于 2013-08-12T13:58:44.133 に答える
0

json オブジェクトの作成方法を次のように変更すると:-

{"1":77937,"2":20,"4":25,"5":11365}

次に、json_decode() パラメータ 2 を TRUE に設定して使用します。つまり、json を配列に変換します。

次に、ID をキーとして使用できる assoc 配列を次のように取得します。

<?php
    $json = '{"1":77937,"2":20,"4":25,"5":11365}';
    $json_array = json_decode($json, TRUE);
    print_r( $json_array);
?>

この配列の結果

Array
(
    [1] => 77937
    [2] => 20
    [4] => 25
    [5] => 11365
)

簡単にできること

 $number = json_array( $valdefined );

またはまだ良い

if ( array_key_exists( $valdefined, $json_array ) ) {
   $number = json_array( $valdefined );
} else {
   $number = NULL;   // or whatever value indicates its NON-EXISTANCE
}
于 2013-08-12T14:58:41.570 に答える