合并多维数组并对在另一列中共享公共值的列值求和
Merge multi-dimensional arrays and sum column values which share a common value in another column
我有 3 个数组用于存储 post 评论和点赞。
这些是 JSON 个字符串:
//评论JSON(存储用户和评论点数)
$comments='[
{
"user": "5",
"points": "12"
},
{
"user": "2",
"points": "1"
},
{
"user": "3",
"points": "1"
}
]';
//点赞数(存储用户和点赞数)
$likes='[
{
"user": "1",
"points": 7
},
{
"user": "4",
"points": 4
},
{
"user": "3",
"points": 1
}
]';
//posts(存储用户和post点数)
$posts='[
{
"user": "1",
"points": "6"
},
{
"user": "3",
"points": "2"
},
{
"user": "2",
"points": "1"
}
]';
我将这些 JSON 转换成这样的数组:
$comment_array = json_decode($comments,TRUE);
$like_array = json_decode($likes,TRUE);
$post_array = json_decode($posts,TRUE);
//echo '<pre>';
//print_r($comment_array);
//print_r($like_array);
//print_r($post_array);
//echo '</pre>';
现在,我正在尝试对这些点求和并将结果保存在一个新数组中。用户应该在所有三个数组中都有条目并不是强制性的。这取决于用户是否发表评论,post或喜欢。
function mergeArrays($filenames, $titles, $descriptions) {
$result = array();
foreach ( $filenames as $key=>$name ) {
$result[] = array( 'filename' => $name, 'title' => $titles[$key], 'descriptions' => $descriptions[ $key ] );
}
return $result;
}
以上函数可以将三个数组全部合并
$merged= mergeArrays($comment_array, $like_array, $post_array);
echo '<pre>';
print_r($merged);
echo '</pre>';
但是,合并后的每个数组都存储为一个索引元素。
我怎样才能得到这样的结果:
$result='[
{
"user": "1",
"points": "13"
},
{
"user": "2",
"points": "2"
},
{
"user": "3",
"points": "4"
},
{
"user": "4",
"points": "4"
},
{
"user": "5",
"points": "12"
}
]';
执行以下操作以获得一个包含求和点的数组:
$collections = array(
'comments' => json_decode($comments,TRUE),
'likes' => json_decode($likes,TRUE);,
'posts' => json_decode($posts,TRUE),
);
$newArray = array();
foreach ($collections as $collection) {
foreach ($collection as $user) {
$newArray[$user->user] += $user->points;
}
}
考虑到您的三个数组,此代码将为您提供一个包含以下内容的数组:积分、投票和不同的用户。
编辑:添加额外的数组并打印它以获得问题所需的输出。
$points = 0;
$uniqueUsers = array();
$votes = 0;
$users = 0;
$result = array();
//Comments
if (!empty($comment_array)) {
foreach ($comment_array as $item) {
if (!in_array($item['user'], $uniqueUsers)) {
array_push($uniqueUsers, $item['user']);
$result[$item['user']] = 0;
}
$votes ++;
$result[$item['user']] += $item['points'];
}
}
// Likes
if (!empty($like_array)) {
foreach ($like_array as $item) {
if (!in_array($item['user'], $uniqueUsers)) {
array_push($uniqueUsers, $item['user']);
$result[$item['user']] = 0;
}
$votes ++;
$result[$item['user']] += $item['points'];
}
}
// Posts
if (!empty($post_array)) {
foreach ($post_array as $item) {
if (!in_array($item['user'], $uniqueUsers)) {
array_push($uniqueUsers, $item['user']);
$result[$item['user']] = 0;
}
$votes ++;
$result[$item['user']] += $item['points'];
}
}
foreach ($result as $idUser=>$points) {
echo "\n";
echo "\n" . 'User: ' . $idUser;
echo "\n" . 'Points: ' . $points;
}
$results = array('users'=> count($uniqueUsers), 'votes'=>$votes, 'points'=> $points);
//print_r($results);
使用array_column
、array_walk_recursive
和array_values
函数的解决方案:
...
$comments = array_column($comment_array, 'points', 'user');
$likes = array_column($like_array, 'points', 'user');
$posts = array_column($post_array, 'points', 'user');
$list = [$comments, $likes, $posts];
$result = [];
array_walk_recursive($list, function($v, $k) use(&$result){
if (key_exists($k, $result)){
$result[$k]['points'] += $v;
} else {
$result[$k] = ['user' => $k, 'points' => $v];
}
});
$result = array_values($result);
print_r($result);
输出:
Array
(
[0] => Array
(
[user] => 5
[points] => 12
)
[1] => Array
(
[user] => 2
[points] => 2
)
[2] => Array
(
[user] => 3
[points] => 4
)
[3] => Array
(
[user] => 1
[points] => 13
)
[4] => Array
(
[user] => 4
[points] => 4
)
)
如果您想学习 "best" 处理这些类型操作的方法,有两点很重要。
当可以使用 isset()
时,不要使用重复的 in_array()
调用。这是因为 isset()
比 in_array()
.
效率高得多
使用临时键来识别重复项,然后在完成后重新索引您的结果——通常使用 array_values()
,但这次我使用 array_multisort()
来重新排序结果和重新索引。
代码:(Demo)
$merged = array_merge(json_decode($comments, true), json_decode($likes, true), json_decode($posts, true));
$result = [];
foreach ($merged as $entry) {
if (!isset($result[$entry['user']])) {
$result[$entry['user']] = $entry;
} else {
$result[$entry['user']]['points'] += $entry['points'];
}
}
array_multisort(array_column($result, 'user'), $result);
// usort($result, function($a, $b) { return $a['user'] <=> $b['user']; });
// array_multisort() will outperform `usort()` in this case.
echo json_encode($result);
输出:
[{"user":"1","points":13},{"user":"2","points":2},{"user":"3","points":4},{"user":"4","points":4},{"user":"5","points":"12"}]
- 解码每个数组并将它们合并成一个多维数组。
- 迭代每个子数组并确定它是否是
user
的第一次出现。如果是这样,保留整个子数组。如果不是,则仅增加该子阵列中的 points
个计数。
- 循环完成后,按
user
升序排序。
这是干净、直接且可读的。
我有 3 个数组用于存储 post 评论和点赞。
这些是 JSON 个字符串:
//评论JSON(存储用户和评论点数)
$comments='[
{
"user": "5",
"points": "12"
},
{
"user": "2",
"points": "1"
},
{
"user": "3",
"points": "1"
}
]';
//点赞数(存储用户和点赞数)
$likes='[
{
"user": "1",
"points": 7
},
{
"user": "4",
"points": 4
},
{
"user": "3",
"points": 1
}
]';
//posts(存储用户和post点数)
$posts='[
{
"user": "1",
"points": "6"
},
{
"user": "3",
"points": "2"
},
{
"user": "2",
"points": "1"
}
]';
我将这些 JSON 转换成这样的数组:
$comment_array = json_decode($comments,TRUE);
$like_array = json_decode($likes,TRUE);
$post_array = json_decode($posts,TRUE);
//echo '<pre>';
//print_r($comment_array);
//print_r($like_array);
//print_r($post_array);
//echo '</pre>';
现在,我正在尝试对这些点求和并将结果保存在一个新数组中。用户应该在所有三个数组中都有条目并不是强制性的。这取决于用户是否发表评论,post或喜欢。
function mergeArrays($filenames, $titles, $descriptions) {
$result = array();
foreach ( $filenames as $key=>$name ) {
$result[] = array( 'filename' => $name, 'title' => $titles[$key], 'descriptions' => $descriptions[ $key ] );
}
return $result;
}
以上函数可以将三个数组全部合并
$merged= mergeArrays($comment_array, $like_array, $post_array);
echo '<pre>';
print_r($merged);
echo '</pre>';
但是,合并后的每个数组都存储为一个索引元素。
我怎样才能得到这样的结果:
$result='[
{
"user": "1",
"points": "13"
},
{
"user": "2",
"points": "2"
},
{
"user": "3",
"points": "4"
},
{
"user": "4",
"points": "4"
},
{
"user": "5",
"points": "12"
}
]';
执行以下操作以获得一个包含求和点的数组:
$collections = array(
'comments' => json_decode($comments,TRUE),
'likes' => json_decode($likes,TRUE);,
'posts' => json_decode($posts,TRUE),
);
$newArray = array();
foreach ($collections as $collection) {
foreach ($collection as $user) {
$newArray[$user->user] += $user->points;
}
}
考虑到您的三个数组,此代码将为您提供一个包含以下内容的数组:积分、投票和不同的用户。
编辑:添加额外的数组并打印它以获得问题所需的输出。
$points = 0;
$uniqueUsers = array();
$votes = 0;
$users = 0;
$result = array();
//Comments
if (!empty($comment_array)) {
foreach ($comment_array as $item) {
if (!in_array($item['user'], $uniqueUsers)) {
array_push($uniqueUsers, $item['user']);
$result[$item['user']] = 0;
}
$votes ++;
$result[$item['user']] += $item['points'];
}
}
// Likes
if (!empty($like_array)) {
foreach ($like_array as $item) {
if (!in_array($item['user'], $uniqueUsers)) {
array_push($uniqueUsers, $item['user']);
$result[$item['user']] = 0;
}
$votes ++;
$result[$item['user']] += $item['points'];
}
}
// Posts
if (!empty($post_array)) {
foreach ($post_array as $item) {
if (!in_array($item['user'], $uniqueUsers)) {
array_push($uniqueUsers, $item['user']);
$result[$item['user']] = 0;
}
$votes ++;
$result[$item['user']] += $item['points'];
}
}
foreach ($result as $idUser=>$points) {
echo "\n";
echo "\n" . 'User: ' . $idUser;
echo "\n" . 'Points: ' . $points;
}
$results = array('users'=> count($uniqueUsers), 'votes'=>$votes, 'points'=> $points);
//print_r($results);
使用array_column
、array_walk_recursive
和array_values
函数的解决方案:
...
$comments = array_column($comment_array, 'points', 'user');
$likes = array_column($like_array, 'points', 'user');
$posts = array_column($post_array, 'points', 'user');
$list = [$comments, $likes, $posts];
$result = [];
array_walk_recursive($list, function($v, $k) use(&$result){
if (key_exists($k, $result)){
$result[$k]['points'] += $v;
} else {
$result[$k] = ['user' => $k, 'points' => $v];
}
});
$result = array_values($result);
print_r($result);
输出:
Array
(
[0] => Array
(
[user] => 5
[points] => 12
)
[1] => Array
(
[user] => 2
[points] => 2
)
[2] => Array
(
[user] => 3
[points] => 4
)
[3] => Array
(
[user] => 1
[points] => 13
)
[4] => Array
(
[user] => 4
[points] => 4
)
)
如果您想学习 "best" 处理这些类型操作的方法,有两点很重要。
当可以使用
isset()
时,不要使用重复的in_array()
调用。这是因为isset()
比in_array()
. 效率高得多
使用临时键来识别重复项,然后在完成后重新索引您的结果——通常使用
array_values()
,但这次我使用array_multisort()
来重新排序结果和重新索引。
代码:(Demo)
$merged = array_merge(json_decode($comments, true), json_decode($likes, true), json_decode($posts, true));
$result = [];
foreach ($merged as $entry) {
if (!isset($result[$entry['user']])) {
$result[$entry['user']] = $entry;
} else {
$result[$entry['user']]['points'] += $entry['points'];
}
}
array_multisort(array_column($result, 'user'), $result);
// usort($result, function($a, $b) { return $a['user'] <=> $b['user']; });
// array_multisort() will outperform `usort()` in this case.
echo json_encode($result);
输出:
[{"user":"1","points":13},{"user":"2","points":2},{"user":"3","points":4},{"user":"4","points":4},{"user":"5","points":"12"}]
- 解码每个数组并将它们合并成一个多维数组。
- 迭代每个子数组并确定它是否是
user
的第一次出现。如果是这样,保留整个子数组。如果不是,则仅增加该子阵列中的points
个计数。 - 循环完成后,按
user
升序排序。
这是干净、直接且可读的。