根据属性值有效地找到嵌套的PHP数组元素

根据属性值有效地找到嵌套的PHP数组元素

问题描述:

Suppose a PHP array, when cast to JSON, has the following format:

[{
    "key": "width",
    "value": "1200",
    "label": "Width (mm)",
    "choice": ""
},
{
    "key": "height",
    "value": "900",
    "label": "Height (mm)",
    "choice": ""
},
{
    "key": "material",
    "value": "paper",
    "label": "Material",
    "choice": "Paper"
}]

(This is a shortened version of the original, which can have many more elements)

Let's suppose I want to efficiently find what material is used. In other words, I want to search for a nested array that has for key the value material, and I want to return the value which would be paper.

I know this can be done by using a foreach/while loop, but PHP is rich with compiled array functions that I'm not very familiar with. What's the best function to use here?


UPDATE: What I've tried so far

Here's two things I've tried so far:

Attempt #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'];
  }
}

Attempt #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'];

Both produce the right value, but #1 is messy, and #2 may not be the best use of PHPs array functions.

假设PHP数组在转换为JSON时具有以下格式: p> [{ “key”:“width”, “value”:“1200”, “label”:“Width(mm)”, “choice”:“” }, { “key”:“height”, “value”:“900”, “label”:“Height(mm)”, “choice”:“” }, { “key”:“material”, “value”:“paper”, “label”:“Material”, “choice”:“Paper” }] code> pre>

(这是原版的缩短版,可以有更多的元素) p>

让我们假设我想有效地找到什么材料 用来。 换句话说,我想搜索一个嵌套数组,其中包含 key code>值 material code>,我想返回值 code> 是 paper code>。 p>

我知道这可以通过使用foreach / while循环来完成,但是PHP有很多编译的数组函数,我不是很熟悉 用。 在这里使用的最佳功能是什么? p>


更新:到目前为止我尝试了什么 strong> p>

到目前为止,我已经尝试了两件事: p>

尝试#1: p>

  $ 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']; 
} 
} 
  code>  pre> 
 
 

尝试#2: p> \ n

  $ 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){\  n return($ array ['key'] =='material'); 
}); 
 $ arr = arra  y_pop($ filteredArray)['value']; 
  code>  pre> 
 
 

两者都产生正确的值,但#1是凌乱的,#2 可能不是PHPs数组函数的最佳用法。 p> div>

It depends on what you want to do in addition to "finding the value". And what you have.

array_filter is simple, but it will loop through the whole array.

array_search on a reduced set looks faster, but it needs to make a copy of the source array, so it's actually slower than array_filter (not by much).

The foreach solution you tried first will not create extra arrays and it allows you to break on a find:

foreach($array as $nestedArray) {
    if ($nestedArray['key'] == 'material') {
        $material = $nestedArray['value'];
        break; // <--- found!
    }
}

So on short arrays I'd go with the accepted solution using array_column, or if you're sure that the material is there, there is this array_column tweak:

// Transform the records into keypairs
$keypairs = array_column($records, 'value', 'key');

Now keypairs is [ width => 900, material => paper, ... ], so:

$material = $keypairs['material'];

I'd add a array_key_exists just to be sure. This saves the array_search (not that great an advantage, but you might have a use for the keypair object).

If you need exactly that one value and nothing else, performance is at a premium, and the array is large, I'd not throw out the idea of looking for '"material":"' inside the JSON as a string with strpos, even if it's a code smell.

If it's a json text as you stated in comments my advice is a regex match.

This will find "key material" and "value" and match the value of value.
It works on the small sample, but you have to try it on a larger string.

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);

You can use combination of array_search and array_column so no need to use loop

Working Demo: 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'];

Output

paper