PHP поиск JSON без зацикливания - PullRequest
0 голосов
/ 11 июня 2018

У меня большой массив JSON, который является результатом запроса API системы мониторинга Icinga2.

Я использовал в своем коде json_decode, подобный этому:

$response = json_decode($array, true);

и я вижу, что результат выглядит следующим образом:

        Array
            (
                [results] => Array
                    (
                        [0] => Array
                            (
                                [attrs] => Array
                                    (
                                        [__name] => HOSTNAME0
                                        [acknowledgement] => 0
                                        [acknowledgement_expiry] => 0
                                        ...
                                        ...
                                        [state] => 0
                                        [state_type] => 1
                                 [meta] => Array
                                     (
                                     )

                                 [name] => HOSTNAME0
                                 [type] => Host
            )


                        [1] => Array
                            (
                                [attrs] => Array
                                    (
                                        [__name] => HOSTNAME1
                                        [acknowledgement] => 0
                                        [acknowledgement_expiry] => 0
                                        ...
                                        ...
                                        [state] => 0
                                        [state_type] => 1   
                                 [meta] => Array
                                     (
                                     )

                                 [name] => HOSTNAME1
                                 [type] => Host
            )

Всего 400 записей, и это довольно сложная структура, но единственные биты, которые меня действительно интересуют - это поля имени и состояния.В основном мой скрипт имеет список из 150 имен хостов из другого источника, и я хочу сделать для каждого хоста имя, найти его в массиве и вернуть значение поля состояния для этого хоста.До сих пор я изо всех сил пытался сделать это, не просматривая весь массив для каждого из 150 имен хостов.Должен быть более эффективный способ поиска в массиве на основе имени хоста и возврата одного значения, но я не могу понять это.

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Я надеюсь, что у меня есть исходный массив данных в правильной компоновке, поскольку формат немного сбивал с толку от первоначального вопроса.Но основная идея состоит в том, чтобы использовать array_column для извлечения «attrs» и ввода результата с помощью элемента «name» этого массива.

$response = Array(
    "results" => Array(
        0 => Array(
            "attrs" => Array(
                "__name" => "HOSTNAME0",
                "acknowledgement" => 0,
                "acknowledgement_expiry" => 0,
                "state" => 0,
                "state_type" => 1
            ),
            "name" => "HOSTNAME0",
            "type" => "Host"
        ),
        1 => Array(
            "attrs" => Array(
                "__name" => "HOSTNAME1",
                "acknowledgement" => 0,
                "acknowledgement_expiry" => 0,
                "state" => 2,
                "state_type" => 1
            ),
            "name" => "HOSTNAME1",
            "type" => "Host1"
        )
    )
);

$extract = array_column($response["results"], "attrs", "name");
print_r($extract);

Для данных примера это дает ...

Array
(
    [HOSTNAME0] => Array
        (
            [__name] => HOSTNAME0
            [acknowledgement] => 0
            [acknowledgement_expiry] => 0
            [state] => 0
            [state_type] => 1
        )

    [HOSTNAME1] => Array
        (
            [__name] => HOSTNAME1
            [acknowledgement] => 0
            [acknowledgement_expiry] => 0
            [state] => 2
            [state_type] => 1
        )

)

Таким образом, чтобы найти любой сервер по имени, вы должны использовать

echo "HOSTNAME1=".$extract["HOSTNAME1"]["state"].PHP_EOL;

Если вы хотите только поле состояния (как вы и просили) и хотите упростить массив, вы можете затемuse ...

array_walk($extract, function(&$data) {$data=$data["state"];});
print_r($extract);

array_walk() проходит через массив и просто копирует поле состояния, чтобы быть записью, поэтому в результате получается ...

Array
(
    [HOSTNAME0] => 0
    [HOSTNAME1] => 2
)

Так что теперь вы просто делаете ...

echo "HOSTNAME1=".$extract["HOSTNAME1"].PHP_EOL;
0 голосов
/ 11 июня 2018

Учитывая, что поле name не имеет логической сортировки внутри результата json, нет способа посмотреть хотя бы один раз на каждый элемент.Если они отсортированы по алфавиту, вы можете использовать простой двоичный поиск, который даст вам результат в O(log(n)).

Другое дело, что если вам нужно искать несколько имен, вы можете поместить их внутрисвязанный с именем массив.Таким образом, у вас есть только начальные накладные расходы O(n) для построения списка, и каждый следующий поиск вернет вам состояние на O(1).

// building the array
$states = [];
foreach ($items as $item) {
    $states[$item['name']] = $item['state'];
}

looking for HOSTNAME1
$state = $states['HOSTNAME1'];
...