合并多维数组并对在另一列中共享公共值的列值求和

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_columnarray_walk_recursivearray_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" 处理这些类型操作的方法,有两点很重要。

  1. 当可以使用 isset() 时,不要使用重复的 in_array() 调用。这是因为 isset()in_array().

  2. 效率高得多
  3. 使用临时键来识别重复项,然后在完成后重新索引您的结果——通常使用 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升序排序。

这是干净、直接且可读的。