通过在PHP中匹配对象字段,在单个数组中组合对象值
我一直在四处挖掘,试图以尽可能干净的方式解决这个问题,但还没有找到正确的方法 我有一个这样的对象数组:通过在PHP中匹配对象字段,在单个数组中组合对象值,php,arrays,Php,Arrays,我一直在四处挖掘,试图以尽可能干净的方式解决这个问题,但还没有找到正确的方法 我有一个这样的对象数组: $myArray = [ {field: "Diameter", measurement: 15, count: 4}, {field: "Diameter", measurement: 16, count: 1}, {field: "Diameter", measurement: 17, count: 15}
$myArray = [
{field: "Diameter", measurement: 15, count: 4},
{field: "Diameter", measurement: 16, count: 1},
{field: "Diameter", measurement: 17, count: 15},
{field: "Width", measurement: 7, count: 12},
{field: "Width", measurement: 8, count: 8},
{field: "Brands", measurement: "blah", count: 1},
{field: "Brands", measurement: "doubleBlah", count: 3},
{field: "Brands", measurement: "blah", count: 1},
{field: "Brands", measurement: "doubleBlah", count: 3},
{field: "Brands", measurement: "blah", count: 12}
]
我需要组合具有重复测量场的对象,并像这样组合计数:
$myBetterArray = [
{field: "Diameter", measurement: 15, count: 4},
{field: "Diameter", measurement: 16, count: 1},
{field: "Diameter", measurement: 17, count: 15},
{field: "Width", measurement: 7, count: 12},
{field: "Width", measurement: 8, count: 8},
{field: "Brands", measurement: "blah", count: 14},
{field: "Brands", measurement: "doubleBlah", count: 6},
]
[
{"field":"Brands","measurement":"blah","count":1},
{"field":"Brands","measurement":"blah","count":1},
{"field":"Brands","measurement":"blah","count":12},
{"field":"Brands","measurement":"doubleBlah","count":3},
{"field":"Brands","measurement":"doubleBlah","count":3},
{"field":"Diameter","measurement":15,"count":4},
{"field":"Diameter","measurement":16,"count":1},
{"field":"Diameter","measurement":17,"count":15},
{"field":"Width","measurement":7,"count":12},
{"field":"Width","measurement":8,"count":8}
]
是否可以使用类似于array_map的东西或同样干净且不太冗长的东西来完成?如果有任何帮助,我将不胜感激。基于这样“隐藏”的密钥、已知的数据格式以及问题的编写方式(“尽可能干净的方式”,“不太冗长”),我只需选择foreach():
在可以使用密钥的中间数组中处理数据(如果不这样做,以后搜索给定的密钥对会更复杂),然后使用另一个foreach将结果以所需格式组合在一起
这对于两个级别应该足够了。另外,最好将代码放在一个函数中,以防止$\u im污染名称空间
(object)[]
是一种将数组强制转换为对象(stdClass)的简单方法,因为这似乎就是问题中的数据格式
??0
为当前$\u im[$item->field][$item->measurement]
尚未存在时的情况创建一个起始值(即,每次有新字段时,测量对)。写入时间比使用isset()短。首先对数组进行排序,以便所有可能连接的测量值都是连续的;这将允许您仅检查连续元素
这种方法使更改每个记录的字段规范(也称为签名或综合征)变得更容易,使用的内存更少,并且在非常长的数组中可以抵抗“Schlemiel the Painter”问题
$keys = [ 'field', 'measurement' ];
uasort($array, function($item1, $item2) use ($keys) {
foreach ($keys as $key) {
if ($item1[$key] === $item2[$key]) {
continue;
}
if ($item1[$key] < $item2[$key]) {
return -1;
}
return 1;
}
return 0;
});
// This is to be sure that the array will reencode as a JSON array
$array = array_values($array);
现在,扫描合并具有相同密钥综合征的计数的数组
$j = -1;
$advance = true;
foreach ($array as $i => $row) {
if ($j >= 0) {
$advance = false;
foreach ($keys as $key) {
if ($array[$i][$key] !== $array[$j][$key]) {
$advance = true;
break;
}
}
if (!$advance) {
// Row $i is a duplicate of row $j
$array[$j]['count'] += $array[$i]['count'];
}
}
if ($advance) {
// Row $i is moved in row $j
$j++;
if ($j !== $i) {
$array[$j] = $array[$i];
}
}
}
// All rows past j must be deleted
$array = array_slice($array, 0, $j+1);
阵列现在是:
[
{"field":"Brands","measurement":"blah","count":14},
{"field":"Brands","measurement":"doubleBlah","count":6},
{"field":"Diameter","measurement":15,"count":4},
{"field":"Diameter","measurement":16,"count":1},
{"field":"Diameter","measurement":17,"count":15},
{"field":"Width","measurement":7,"count":12},
{"field":"Width","measurement":8,"count":8}
]
我似乎无法在PHP7.4.3上运行此代码。如果我将
compact()
替换为$res[]=['field'=>$field',measurement'=>$measurement',count'=>$count]
(我仍然收到一些E_通知消息)@LSerni My bad,compact()需要变量名,而不是变量本身。我必须将这行更改为:$\u im[$item['field']][$item['measurement']=$item['count']+($\u im[$item['field']][$item['measurement']]?\0)代码>但是这样做的技巧,它不是太冗长,谢谢@BRose好的,$item是数组,不是对象?对不起,我当时误解了数据。很高兴它成功了!
[
{"field":"Brands","measurement":"blah","count":14},
{"field":"Brands","measurement":"doubleBlah","count":6},
{"field":"Diameter","measurement":15,"count":4},
{"field":"Diameter","measurement":16,"count":1},
{"field":"Diameter","measurement":17,"count":15},
{"field":"Width","measurement":7,"count":12},
{"field":"Width","measurement":8,"count":8}
]