Предположим, что массив PHP, когда он передан в JSON, имеет следующий формат:
[{ "key": "width", "value": "1200", "label": "Width (mm)", "choice": "" }, { "key": "height", "value": "900", "label": "Height (mm)", "choice": "" }, { "key": "material", "value": "paper", "label": "Material", "choice": "Paper" }]
(Это сокращенная версия оригинала, которая может содержать гораздо больше элементов)
Предположим, я хочу эффективно найти, какой материал используется. Другими словами, я хочу найти вложенный массив, который имеет для key
значение material
, и я хочу вернуть value
которое будет paper
.
Я знаю, что это можно сделать, используя цикл foreach / while, но PHP богат скомпилированными функциями массива, с которыми я не очень хорошо знаком. Какая функция лучше всего использовать здесь?
ОБНОВЛЕНИЕ: что я пробовал до сих пор
Вот две вещи, которые я пробовал до сих пор:
Попытка № 1:
$json = '[{"key":"width","value":"1200","label":"Width (mm)","choice":""},{"key":"height","value":"900","label":"Height (mm)","choice":""},{"key":"material","value":"paper","label":"Material","choice":"Paper"}]'; $array = json_encode($json, true); $material = ''; foreach($array as $nestedArray) { if($nestedArray['key'] = 'material') { $material = $nestedArray['value']; } }
Попытка № 2:
$json = '[{"key":"width","value":"1200","label":"Width (mm)","choice":""},{"key":"height","value":"900","label":"Height (mm)","choice":""},{"key":"material","value":"paper","label":"Material","choice":"Paper"}]'; $array = json_decode($json, true); $filteredArray = array_filter($array, function($array) { return ($array['key'] == 'material'); }); $arr = array_pop($filteredArray)['value'];
Оба генерируют правильное значение, но # 1 беспорядочно, а # 2 – не лучшее использование функций массива PHP.
Это зависит от того, что вы хотите сделать в дополнение к «нахождению значения». И что у вас есть.
array_filter
прост, но он будет проходить через весь массив.
array_search
на уменьшенном наборе выглядит быстрее, но он должен сделать копию исходного массива, поэтому он на самом деле медленнее, чем array_filter
(не сильно).
Решение foreach
вы пробовали вначале, не будет создавать дополнительные массивы, и это позволит вам разбить находку:
foreach($array as $nestedArray) { if ($nestedArray['key'] == 'material') { $material = $nestedArray['value']; break; // <--- found! } }
Поэтому на коротких массивах я бы пошел с принятым решением, используя array_column
, или если вы уверены, что материал есть, есть эта настройка array_column
:
// Transform the records into keypairs $keypairs = array_column($records, 'value', 'key');
Теперь клавиши [ширина => 900, материал => бумага, …], поэтому:
$material = $keypairs['material'];
Я бы добавил array_key_exists
чтобы быть уверенным. Это сохраняет array_search
(не такое большое преимущество, но вы можете использовать объект keypair).
Если вам нужно именно это одно значение и ничего больше, производительность в порядке, а массив большой, я бы не выбрал идею поиска «материала»: «внутри JSON в виде строки с strpos
, даже если это запах кода.
Если это json-текст, который вы указали в комментариях, мой совет – это регулярное совпадение.
Это найдет «ключевой материал» и «значение» и соответствует значению стоимости.
Он работает с небольшим образцом, но вы должны попробовать его на большей строке.
https://regex101.com/r/CSTLUL/1
$re = '/key\": \"material\",.*?\"value\": \"(.*?)\",/s'; $str = '{ "key": "width", "value": "1200", "label": "Width (mm)", "choice": "" }, { "key": "height", "value": "900", "label": "Height (mm)", "choice": "" }, { "key": "material", "value": "paper", "label": "Material", "choice": "Paper" }]'; preg_match_all($re, $str, $matches); // Print the entire match result var_dump($matches);
Вы можете использовать комбинацию array_search и array_column, поэтому нет необходимости использовать цикл
Рабочая демонстрация : https://eval.in/865566
$data = '[{ "key": "width", "value": "1200", "label": "Width (mm)", "choice": "" }, { "key": "height", "value": "900", "label": "Height (mm)", "choice": "" }, { "key": "material", "value": "paper", "label": "Material", "choice": "Paper" }]'; $data = json_decode($data,True); $key = array_search('material', array_column($data, 'key')); // get key of array echo $data[$key]['value'];
Вывод
paper