簡體   English   中英

合並多維數組並對在另一列中共享公共值的列值求和

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

我有 3 個用於存儲帖子、評論和喜歡的數組。

這些是 JSON 字符串:

//comments 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(存儲用戶和發布點)

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

現在,我正在嘗試對這些點求和並將結果保存在一個新數組中。 用戶不必在所有三個數組中都有條目。 這取決於用戶是否發表了評論、帖子或點贊。

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"
    }
]';

考慮到您的三個數組,此代碼將為您提供一個包含以下內容的數組:點數、投票數和不同的用戶。

編輯:添加額外的數組並打印它以獲得 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);

使用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
        )
)

執行以下操作以得到一個帶有總和點的數組:

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

如果您想學習處理這些類型操作的“最佳”方法,有兩個要點需要說明。

  1. 當可以使用isset()代替時,不要使用迭代的in_array()調用。 這是因為isset()in_array()高效得多。

  2. 使用臨時鍵來識別重復的事件,然后在完成后重新索引結果——通常使用array_values() ,但這次我使用array_multisort()重新排序結果並重新索引。

代碼:(演示

$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升序排序。

這是干凈、直接和可讀的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM