如何对关联数组数组进行分组并声明自定义键?



有人可以帮助我以分组格式转换 php 数组吗?我正在尝试按id对它们进行分组.我想转换以下数组:

$Arr1=Array
(
0 => Array
(
"id" => "4123",
"test_number" => "1",
"sat_total" => "1050"
),
1 => Array
(
"id" => "4123",
"test_number" => "2",
"sat_total" => "1130"
),
2 => Array
(
"id" => "4123",
"test_number" => "3",
"sat_total" => "1120"
),
3 => Array
(
"id" => "5555",
"test_number" => "1",
"sat_total" => "1130"
),
4 => Array
(
"id" => "5555",
"test_number" => "2",
"sat_total" => "1160"
)
);

进入这个:

$Arr2=Array
(
0 => Array
(
"id" => "4123",
"Score1" => "1050",
"Score2" => "1130",
"Score3" => "1120"
),
1 => Array
(
"id" => "5555",
"Score1" => "1130",
"Score2" => "1160"
)
);

我已经尝试了一点,但似乎找不到如何使其工作。

您只需要迭代数据行,确定每一行是否是第一个出现的id值,然后声明初始值,或向组添加一个可变键元素。 循环完成后,调用array_values()为数组重新编制索引(删除临时键(。

代码:(演示(

$Arr1=[
["id" => "4123", "test_number" => "1", "sat_total" => "1050"],
["id" => "4123", "test_number" => "2", "sat_total" => "1130"],
["id" => "4123", "test_number" => "3", "sat_total" => "1120"],
["id" => "5555", "test_number" => "1", "sat_total" => "1130"],
["id" => "5555", "test_number" => "2", "sat_total" => "1160"]
];
foreach ($Arr1 as $set) {
if (!isset($result[$set['id']])) {
$result[$set['id']] = ['id' => $set['id'], 'Score1' => $set['sat_total']];
} else {
$result[$set['id']]['Score' . sizeof($result[$set['id']])] = $set['sat_total'];
}
}
var_export(array_values($result));

输出:

array (
0 => 
array (
'id' => '4123',
'Score1' => '1050',
'Score2' => '1130',
'Score3' => '1120',
),
1 => 
array (
'id' => '5555',
'Score1' => '1130',
'Score2' => '1160',
),
)

此方法将找到与$id匹配的分数。
它使用三个array_intersects来匹配所有正确的值。
此方法只会循环唯一 ID 的数量,在您的情况下会循环两次。
加上创建记分键的时间。

我确实同意ggorlen关于钥匙的说法。这也将创建一个更有效的代码。

$ids = array_column($Arr1, "id");
$sat = array_column($Arr1, "sat_total");
foreach(array_unique($ids) as $id){
$new[$id] = ["id" => $id];
$tmp = array_values(array_intersect_key($sat,array_intersect_key($Arr1, array_intersect($ids, [$id]))));
for($i=1;$i<=count($tmp);$i++) $new[$id]["Score" . $i] = $tmp[$i-1];
}
var_dump($new);

https://3v4l.org/ag3To

输出是一个以 id 作为键的关联数组。
如果要将其编入索引,可以使用array_values。


只是为了展示使用一个分数数组的代码效率可以提高多少。
这是它的样子:

$ids = array_column($Arr1, "id");
$sat = array_column($Arr1, "sat_total");
foreach(array_unique($ids) as $id){
$new[] = ["id" => $id, "scores" => array_values(array_intersect_key($sat,array_intersect_key($Arr1, array_intersect($ids, [$id]))))];
}
var_dump($new);

https://3v4l.org/mdA0W

$arr2 = [];
$i = 0;
$length = count($arr1);
do {
$builder = $arr1[$i];
// grab the first item from the original array
$builder = [
// set its initial properties
'id' => $arr1[$i]['id'],
'Score1' => $arr1[$i]['sat_total'],
];
// initialise the subsequent score number
$testNumber = 2;
// prepare to look ahead in the original array for a matching id
while (($i + 1) < $length) { // only look ahead if it is possible to
if ($arr1[$i + 1]['id'] == $builder['id']) {
// did you find a matching id? if so, let's set the subsequent score
$builder["Score$testNumber"] = $arr1[$i + 1]['sat_total'];
$testNumber++; // increase the next score number
$i++; // increase the original array index
} else {
// no luck? let's go forwards and set the next record
break;
}
}
$arr2[] = $builder; // set the built record into the new array
$i++; // move the pointer forwards
} while ($i < $length); // as long as there are items ahead

你很少使用一段时间。但它:)有效

将原始数组$arr1输入它,$arr2将被设置。

它通过期待匹配id来工作。此解决方案假定您的原始阵列按id!因此,除非您信任输入 - 否则不要使用此解决方案!

否则,这是一个简单、快速且相当可读的解决方案,在我看来就像学校练习一样?

如果您想要安全的东西,这里的其他解决方案是合适的。

我不确定这种结构是否理想 - 似乎您的键"Score1""Score2"等最好作为像scores => [1050, 1130, ...]这样的数组,感觉id应该是结果数组中的键。但无论如何,这都会给出您请求的输出:

$res = [];
foreach ($arr as $e) {
if (!array_key_exists($e['id'], $res)) {
$res[$e['id']] = [];
}
$res[$e['id']]["Score".(count($res[$e['id']])+1)] = $e['sat_total'];
}
$count = 0;
foreach ($res as $k => $v) {
$res[$k]['id'] = $k;
$res[$count++] = $res[$k];
unset($res[$k]);
}
print_r($res);

输出

Array
(
[0] => Array
(
[Score1] => 1050
[Score2] => 1130
[Score3] => 1120
[id] => 4123
)
[1] => Array
(
[Score1] => 1130
[Score2] => 1160
[id] => 5555
)
)

请注意,我做了两次传递,这有点冗长,但是花时间在第一次传递中将数据 ID 键入数组应该可以改善通过数组对每个元素的线性搜索到O(1(哈希中,所以我认为额外的循环块是值得的。

最新更新