Search code examples
phpjsonmultidimensional-arraysumarray-merge

Merge multi-dimensional arrays and sum column values which share a common value in another column


I have 3 arrays for storing posts,comments, and likes.

These are the JSON strings:

//comments JSON (stores user and comment points)

$comments='[
    {
        "user": "5",
        "points": "12"
    },
    {
        "user": "2",
        "points": "1"
    },
    {
        "user": "3",
        "points": "1"
    }
]';

//likes(stores user and likes point)

$likes='[
    {
        "user": "1",
        "points": 7
    },
    {
        "user": "4",
        "points": 4
    },
    {
        "user": "3",
        "points": 1
    }
]';

//posts (stores user and post points)

$posts='[
    {
        "user": "1",
        "points": "6"
    },
    {
        "user": "3",
        "points": "2"
    },
    {
        "user": "2",
        "points": "1"
    }
]';

I convert these JSONs into arrays like this:

$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>';

Now, I'm trying to sum these points and save the result in a new array. It's not mandatory that a user should have entries in all the three arrays. It depends on whether a user has made a comment, post or like.

function mergeArrays($filenames, $titles, $descriptions) {
    $result = array();

    foreach ( $filenames as $key=>$name ) {
        $result[] = array( 'filename' => $name, 'title' => $titles[$key], 'descriptions' => $descriptions[ $key ] );
    }

    return $result;
}

The above function can merge all the three arrays.

$merged= mergeArrays($comment_array, $like_array, $post_array);

echo '<pre>';
print_r($merged);
echo '</pre>';

However, each array after merging is stored as an index element.

How can I get a result something like this:

$result='[
    {
        "user": "1",
        "points": "13"
    },
    {
        "user": "2",
        "points": "2"
    },
    {
        "user": "3",
        "points": "4"
    },
    {
        "user": "4",
        "points": "4"
    },
    {
        "user": "5",
        "points": "12"
    }
]';

Solution

  • Considering your three arrays, this code will get you an array with: points, votes and diferent users.

    Edit: Adding additional array and printing it to get the output desired by question.

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