วิธีการรวมค่าคอลัมน์ทั้งหมดในอาร์เรย์หลายมิติ


116

ฉันจะเพิ่มค่าคอลัมน์ทั้งหมดด้วยคีย์การเชื่อมโยงได้อย่างไร โปรดทราบว่าชุดคีย์เป็นแบบไดนามิก

อาร์เรย์อินพุต:

Array
(
    [0] => Array
        (
            [gozhi] => 2
            [uzorong] => 1
            [ngangla] => 4
            [langthel] => 5
        )

    [1] => Array
        (
            [gozhi] => 5
            [uzorong] => 0
            [ngangla] => 3
            [langthel] => 2
        )

    [2] => Array
        (
            [gozhi] => 3
            [uzorong] => 0
            [ngangla] => 1
            [langthel] => 3
        )
)

ผลลัพธ์ที่ต้องการ:

Array
(
    [gozhi] => 10
    [uzorong] => 1
    [ngangla] => 8
    [langthel] => 10
)

สำหรับสถานการณ์ทั่วไปอาร์เรย์หลายมิติสองชุดไม่มีคีย์ที่เหมือนกันทุกประการ merge / sum multi dimentional array php
Kris Roofe

คำตอบ:


92
$sumArray = array();

foreach ($myArray as $k=>$subArray) {
  foreach ($subArray as $id=>$value) {
    $sumArray[$id]+=$value;
  }
}

print_r($sumArray);

49
ซึ่งจะเป็นการแจ้งเตือนสำหรับการทำซ้ำครั้งแรกเนื่องจากยังไม่มีคีย์
Gumbo

ถ้ามี n อาร์เรย์?
Muhammad Usman

2
@RanaMuhammadUsman: หากมีnอาร์เรย์ให้ใช้วิธีนี้
Amal Murali

2
array_reduce ฟังดูสวยที่สุดสำหรับฉันstackoverflow.com/questions/14195916/…
Bill'o

13
เพื่อหลีกเลี่ยงการแจ้งคุณสามารถแทนที่บรรทัดที่กำหนดค่าให้ $ sumArray เป็น: array_key_exists ($ id, $ sumArray)? $ sumArray [$ id] + = $ value: $ sumArray [$ id] = $ value;
Dave O'Brien

185

คุณสามารถใช้array_walk_recursive()เพื่อรับโซลูชันกรณีทั่วไปสำหรับปัญหาของคุณ ( อันที่เมื่ออาร์เรย์ภายในแต่ละอันอาจมีคีย์ที่ไม่ซ้ำกัน )

$final = array();

array_walk_recursive($input, function($item, $key) use (&$final){
    $final[$key] = isset($final[$key]) ?  $item + $final[$key] : $item;
});

ตัวอย่างarray_walk_recursive()สำหรับกรณีทั่วไป

นอกจากนี้ตั้งแต่PHP 5.5คุณสามารถใช้array_column()ฟังก์ชั่นเพื่อให้บรรลุผลที่คุณต้องการสำหรับคีย์ที่แน่นอน , [gozhi]ตัวอย่างเช่น:

array_sum(array_column($input, 'gozhi')); 

ตัวอย่างarray_column()สำหรับคีย์ที่ระบุ

หากคุณต้องการรับผลรวมของอาร์เรย์ภายในทั้งหมดที่มีคีย์เดียวกัน ( ผลลัพธ์ที่คุณต้องการโพสต์ ) คุณสามารถทำสิ่งนี้ได้ ( โปรดจำไว้ว่าอาร์เรย์ภายในแรกต้องมีโครงสร้างเดียวกันกับอาร์เรย์อื่น ๆ ):

$final = array_shift($input);

foreach ($final as $key => &$value){
   $value += array_sum(array_column($input, $key));
}    

unset($value);

ตัวอย่างเช่นarray_column()ในกรณีที่อาร์เรย์ภายในทั้งหมดมีคีย์เดียวกัน

หากคุณต้องการโซลูชันกรณีทั่วไปโดยใช้array_column()ในตอนแรกคุณอาจพิจารณารับคีย์ที่ไม่ซ้ำกันทั้งหมดจากนั้นรับผลรวมสำหรับแต่ละคีย์:

$final = array();

foreach($input as $value)
    $final = array_merge($final, $value);

foreach($final as $key => &$value)
    $value = array_sum(array_column($input, $key));

unset($value);

ตัวอย่างarray_column()สำหรับกรณีทั่วไป


31

ใช้ตัวอย่างข้อมูลนี้:

$key = 'gozhi';
$sum = array_sum(array_column($array,$key));

ฉันได้แก้ไขคำถามเพื่อชี้แจงว่าโซลูชันนี้ค่อนข้างไม่สุกในแง่ของการส่งมอบผลลัพธ์ที่ต้องการของ OP ที่กล่าวว่าหากคุณจะขยายคำตอบของคุณก็มีโอกาสมากที่จะกลายเป็นซ้ำกับคำตอบที่โพสต์ก่อนหน้านี้
mickmackusa

28

นี่คือวิธีแก้ปัญหาที่คล้ายกับอีกสองคน:

$acc = array_shift($arr);
foreach ($arr as $val) {
    foreach ($val as $key => $val) {
        $acc[$key] += $val;
    }
}

แต่ไม่จำเป็นต้องตรวจสอบว่ามีคีย์อาร์เรย์อยู่แล้วหรือไม่และไม่ได้ส่งการแจ้งเตือน


+1 โซลูชันที่ชาญฉลาดมากสำหรับโครงสร้างอาร์เรย์เฉพาะนี้ น่าเสียดายที่มันใช้ไม่ได้ในกรณีทั่วไปของอาร์เรย์ทั้งหมดที่มีโครงสร้างเหมือนกับผลลัพธ์สุดท้าย
Todd Chaffee

22

นอกจากนี้ยังสามารถทำได้โดยใช้array_map:

$rArray = array(
    0 => array(
        'gozhi' => 2,
        'uzorong' => 1,
        'ngangla' => 4,
        'langthel' => 5
    ),
    1 => array(
        'gozhi' => 5,
        'uzorong' => 0,
        'ngangla' => 3,
        'langthel' => 2
    ),
    2 => array(
        'gozhi' => 3,
        'uzorong' => 0,
        'ngangla' => 1,
        'langthel' => 3
    ),
);

$sumResult = call_user_func_array('array_map', array_merge(['sum'], $rArray));

function sum()
{
    return array_sum(func_get_args());
}

1
เหมาะสำหรับ n จำนวนอาร์เรย์
Dushyant Joshi

1
คุณจะเปลี่ยนสิ่งนี้สำหรับอาร์เรย์ N จำนวนได้อย่างไร
Pathros

12
$newarr=array();
foreach($arrs as $value)
{
  foreach($value as $key=>$secondValue)
   {
       if(!isset($newarr[$key]))
        {
           $newarr[$key]=0;
        }
       $newarr[$key]+=$secondValue;
   }
}

3
โปรดทราบว่าสิ่งนี้จะแจ้งให้คุณทราบเกี่ยวกับ PHP (ดัชนีที่ไม่ได้กำหนด) ทุกครั้งที่คุณเข้าถึง $ newarr [$ key] ทางด้านขวาของงานของคุณเมื่อยังไม่มีค่าดังกล่าว
Anti Veeranna

ฉันคิดว่าฉันเพิ่มการตรวจสอบเพื่อเริ่มต้น $ newarr [$ key]
Graviton

4
โปรดแสดงความคิดเห็นหากคุณลงคะแนนให้ใครสักคน ... ไม่มีวิธีใดที่จะปรับปรุงวิธีแก้ปัญหาได้หากคุณไม่แสดงความคิดเห็น
Todd Chaffee

@Graviton ฉันไม่ได้ลงคะแนน แต่ฉันจะระบุว่าทุกคำตอบของ StackOverflow ควรมีคำอธิบายเกี่ยวกับวิธีการแก้ปัญหาและ / หรือเหตุผลที่แนะนำ จำทุกหน้าบนไซต์ / เครือข่ายนี้เป็นแหล่งข้อมูลการศึกษาสำหรับนักพัฒนาหลายพันคนที่มีทักษะ / ความรู้ที่หลากหลาย (ถ้าฉันลงคะแนนทุกครั้งที่ฉันพบคำตอบแบบรหัสเท่านั้นฉันจะหมดคะแนนตัวแทน)
mickmackusa

5

รุ่นอื่นพร้อมสิทธิประโยชน์บางประการด้านล่าง

$sum = ArrayHelper::copyKeys($arr[0]);

foreach ($arr as $item) {
    ArrayHelper::addArrays($sum, $item);
}


class ArrayHelper {

    public function addArrays(Array &$to, Array $from) {
        foreach ($from as $key=>$value) {
            $to[$key] += $value;
        }
    }

    public function copyKeys(Array $from, $init=0) {
        return array_fill_keys(array_keys($from), $init);
    }

}

ฉันต้องการรวมคำตอบที่ดีที่สุดของ Gumbo, Graviton และ Chris J เข้ากับเป้าหมายต่อไปนี้เพื่อที่ฉันจะได้ใช้สิ่งนี้ในแอปของฉัน:

a) เริ่มต้นคีย์อาร์เรย์ 'sum' นอกลูป (Gumbo) ควรช่วยเรื่องประสิทธิภาพในอาร์เรย์ขนาดใหญ่มาก (ยังไม่ได้ทดสอบ!) กำจัดการแจ้งเตือน

b) ตรรกะหลักเข้าใจง่ายโดยไม่ต้องกดปุ่มคู่มือ (กราวิตัน, คริสเจ).

c) แก้ปัญหาทั่วไปในการเพิ่มค่าของอาร์เรย์สองอาร์เรย์ด้วยคีย์เดียวกันและทำให้น้อยลงขึ้นอยู่กับโครงสร้างอาร์เรย์ย่อย

ไม่เหมือนกับโซลูชันของ Gumbo คุณสามารถใช้สิ่งนี้ซ้ำได้ในกรณีที่ค่าไม่อยู่ในอาร์เรย์ย่อย ลองนึกภาพในตัวอย่างด้านล่างว่า$arr1และ$arr2ไม่ใช่ฮาร์ดโค้ด แต่จะถูกส่งกลับอันเป็นผลมาจากการเรียกใช้ฟังก์ชันภายในลูป

$arr1 = array(
    'gozhi' => 2,
    'uzorong' => 1,
    'ngangla' => 4,
    'langthel' => 5
);

$arr2 = array(
   'gozhi' => 5,
   'uzorong' => 0,
   'ngangla' => 3,
   'langthel' => 2
);

$sum = ArrayHelper::copyKeys($arr1);

ArrayHelper::addArrays($sum, $arr1);
ArrayHelper::addArrays($sum, $arr2);

4

นอกจากนี้ยังสามารถทำได้โดยใช้array_walk:

function array_sum_values(array $input, $key) {
   $sum = 0;
   array_walk($input, function($item, $index, $params) {
         if (!empty($item[$params[1]]))
            $params[0] += $item[$params[1]];
      }, array(&$sum, $key)
   );
   return $sum;
}

var_dump(array_sum_values($arr, 'gozhi'));

ไม่สามารถอ่านได้เหมือนโซลูชันก่อนหน้านี้ แต่ใช้งานได้ :)


3

นี่คือเวอร์ชันที่คีย์อาร์เรย์อาจไม่เหมือนกันสำหรับอาร์เรย์ทั้งสอง แต่คุณต้องการให้ทั้งหมดอยู่ที่นั่นในอาร์เรย์สุดท้าย

function array_add_by_key( $array1, $array2 ) {
    foreach ( $array2 as $k => $a ) {
        if ( array_key_exists( $k, $array1 ) ) {
            $array1[$k] += $a;
        } else {
            $array1[$k] = $a;
        }
    }
    return $array1;
}

3

เราต้องตรวจสอบก่อนว่ามีคีย์อาร์เรย์หรือไม่

รหัส:

$sum = array();
foreach ($array as $key => $sub_array) {
    foreach ($sub_array as $sub_key => $value) {

        //If array key doesn't exists then create and initize first before we add a value.
        //Without this we will have an Undefined index error.
        if( ! array_key_exists($sub_key, $sum)) $sum[$sub_key] = 0;

        //Add Value
        $sum[$sub_key]+=$value;
    }
}
print_r($sum);

เอาท์พุทด้วยการตรวจสอบคีย์อาร์เรย์:

Array
(
    [gozhi] => 10
    [uzorong] => 1
    [ngangla] => 8
    [langthel] => 10
)

เอาท์พุทโดยไม่มีการตรวจสอบคีย์อาร์เรย์:

Notice: Undefined index: gozhi in F:\web\index.php on line 37

Notice: Undefined index: uzorong in F:\web\index.php on line 37

Notice: Undefined index: ngangla in F:\web\index.php on line 37

Notice: Undefined index: langthel in F:\web\index.php on line 37

Array
(
    [gozhi] => 10
    [uzorong] => 1
    [ngangla] => 8
    [langthel] => 10
)

นี่เป็นแนวทางปฏิบัติที่ไม่ดีแม้ว่าจะพิมพ์เอาต์พุต ตรวจสอบก่อนเสมอว่ามีคีย์อยู่หรือไม่


1

สำหรับผู้ที่มาที่นี่และกำลังค้นหาโซลูชันที่รวมอาร์เรย์ Nและยังรวมค่าของคีย์ที่เหมือนกันที่พบในอาร์เรย์ N ฉันได้เขียนฟังก์ชันนี้ซึ่งทำงานซ้ำได้เช่นกัน (ดู: https://gist.github.com/Nickology/f700e319cbafab5eaedc )

ตัวอย่าง:

$a = array( "A" => "bob", "sum" => 10, "C" => array("x","y","z" => 50) );
$b = array( "A" => "max", "sum" => 12, "C" => array("x","y","z" => 45) );
$c = array( "A" => "tom", "sum" =>  8, "C" => array("x","y","z" => 50, "w" => 1) );

print_r(array_merge_recursive_numeric($a,$b,$c));

จะส่งผลให้:

Array
(
    [A] => tom
    [sum] => 30
    [C] => Array
        (
            [0] => x
            [1] => y
            [z] => 145
            [w] => 1
        )

)

นี่คือรหัส:

<?php 
/**
 * array_merge_recursive_numeric function.  Merges N arrays into one array AND sums the values of identical keys.
 * WARNING: If keys have values of different types, the latter values replace the previous ones.
 * 
 * Source: https://gist.github.com/Nickology/f700e319cbafab5eaedc
 * @params N arrays (all parameters must be arrays)
 * @author Nick Jouannem <nick@nickology.com>
 * @access public
 * @return void
 */
function array_merge_recursive_numeric() {

    // Gather all arrays
    $arrays = func_get_args();

    // If there's only one array, it's already merged
    if (count($arrays)==1) {
        return $arrays[0];
    }

    // Remove any items in $arrays that are NOT arrays
    foreach($arrays as $key => $array) {
        if (!is_array($array)) {
            unset($arrays[$key]);
        }
    }

    // We start by setting the first array as our final array.
    // We will merge all other arrays with this one.
    $final = array_shift($arrays);

    foreach($arrays as $b) {

        foreach($final as $key => $value) {

            // If $key does not exist in $b, then it is unique and can be safely merged
            if (!isset($b[$key])) {

                $final[$key] = $value;

            } else {

                // If $key is present in $b, then we need to merge and sum numeric values in both
                if ( is_numeric($value) && is_numeric($b[$key]) ) {
                    // If both values for these keys are numeric, we sum them
                    $final[$key] = $value + $b[$key];
                } else if (is_array($value) && is_array($b[$key])) {
                    // If both values are arrays, we recursively call ourself
                    $final[$key] = array_merge_recursive_numeric($value, $b[$key]);
                } else {
                    // If both keys exist but differ in type, then we cannot merge them.
                    // In this scenario, we will $b's value for $key is used
                    $final[$key] = $b[$key];
                }

            }

        }

        // Finally, we need to merge any keys that exist only in $b
        foreach($b as $key => $value) {
            if (!isset($final[$key])) {
                $final[$key] = $value;
            }
        }

    }

    return $final;

}

?>

1

ตรวจดูแต่ละรายการของอาร์เรย์และรวมค่าเป็นค่าก่อนหน้าหากมีอยู่หากไม่เพียงกำหนดค่า

<?php
$array = 
[
    [
        'a'=>1,
        'b'=>1,
        'c'=>1,
    ],
    [
        'a'=>2,
        'b'=>2,
    ],
    [
        'a'=>3,
        'd'=>3,
    ]
];

$result = array_reduce($array, function($carry, $item) {
    foreach($item as $k => $v)
        $carry[$k] = $v + ($carry[$k] ?? 0);

    return $carry;
}, []);

print_r($result);

เอาท์พุท:

Array
(
    [a] => 6
    [b] => 3
    [c] => 1
    [d] => 3
)

หรือเพียงแค่วนลูปผ่านอาร์เรย์ย่อยแต่ละรายการและจัดกลุ่มค่าสำหรับแต่ละคอลัมน์ สรุปได้ในที่สุด:

foreach($array as $subarray)
    foreach($subarray as $key => $value)
        $grouped[$key][] = $value;

$sums = array_map('array_sum', $grouped);

0

คุณมีวิธีที่ฉันมักจะดำเนินการประเภทนี้

// We declare an empty array in wich we will store the results
$sumArray = array();

// We loop through all the key-value pairs in $myArray
foreach ($myArray as $k=>$subArray) {

   // Each value is an array, we loop through it
   foreach ($subArray as $id=>$value) {

       // If $sumArray has not $id as key we initialize it to zero  
       if(!isset($sumArray[$id])){
           $sumArray[$id] = 0;
       }

       // If the array already has a key named $id, we increment its value
       $sumArray[$id]+=$value;
    }
 }

 print_r($sumArray);

โปรดให้คำอธิบายเกี่ยวกับรหัสนี้และทำไมจึงตอบคำถามได้ จะมีประโยชน์มากกว่าการทิ้งบล็อกโค้ดโดยไม่มีคำอธิบายใด ๆ
trincot

แน่นอน!! ขอโทษฉันเป็นคนสเปนและสำหรับฉันอธิบายว่ารหัสเป็นสิ่งที่ยากที่สุดเมื่อฉันตอบคำถาม! ขอบคุณสำหรับคำแนะนำ @trincot
Luis González

0

คุณสามารถลองสิ่งนี้:

$c = array_map(function () {
      return array_sum(func_get_args());
     },$a, $b);

และในที่สุดก็:

print_r($c);

1
คุณใช้ทำอะไร$aและ$bโทรเมื่อไหร่array_map()? โปรดปรับปรุงคำตอบเฉพาะรหัสนี้
mickmackusa

0

สิ่งนี้ใช้ได้ดีกับโครงการ laravel ของฉัน

print_r($Array); // your original array

$_SUM = [];

// count($Array[0]) => if the number of keys are equall in all arrays then do a count of index 0 etc.
for ($i=0; $i < count($Array[0]); $i++) {
    $_SUM[] = $Array[0][$i] + $Array[1][$i]; // do a for loop on the count 
}

print_r($_SUM); // get a sumed up array

แม้ว่าสิ่งนี้อาจใช้ได้ผลกับโครงการ Laravel ของคุณ แต่นี่ไม่ใช่วิธีแก้ปัญหาที่ดี / ใช้งานได้สำหรับคำถามนี้
mickmackusa

-1
$sumArray = array();
foreach ($myArray as $k => $subArray) {
    foreach ($subArray as $id => $value) {
        if (!isset($sumArray[$id])) {
            $sumArray[$id] = 0;
        }
        $sumArray[$id]+=$value;
    }
}

นี่เป็นคำตอบที่ซ้ำกันจากหลายปีก่อนหน้านี้ stackoverflow.com/a/1496697/2943403 โปรดอ่านคำตอบที่มีอยู่ทั้งหมดก่อนโพสต์ของคุณเองเพื่อไม่ให้เกิดความซ้ำซ้อนในหน้าเดียวกัน
mickmackusa

-1
$sumArray = array();

foreach ($myArray as $k=>$subArray) {
  foreach ($subArray as $id=>$value) {
    if(!isset($sumArray[$id])){
     $sumArray[$id] =$value;
    }else {
     $sumArray[$id]+=$value;
    }
  }
}

print_r($sumArray);

`

โปรดตรวจสอบฉันจะเขียนคำตอบที่ดีได้อย่างไร คำตอบแบบใช้รหัสเท่านั้นไม่ได้รับการสนับสนุนเนื่องจากไม่ได้อธิบายว่าจะแก้ไขปัญหาในคำถามอย่างไร คุณควรอัปเดตคำตอบของคุณเพื่ออธิบายว่าสิ่งนี้ทำอะไรได้บ้างและจะปรับปรุงได้อย่างไรสำหรับคำตอบที่ได้รับการโหวตจำนวนมากที่คำถาม 8 ปีนี้มีอยู่แล้ว
FluffyKitten

โดยทั่วไปจะซ้ำกับคำตอบก่อนหน้านี้: stackoverflow.com/a/20532196/2943403
mickmackusa

-2

ตัวอย่างเช่นคุณสามารถดึงฟิลด์ทั้งหมดจากผลลัพธ์เช่นนี้ด้านล่าง

ฉันกำลังเลือก 'ยอดคงเหลือ' จากอาร์เรย์และบันทึกลงในตัวแปร

$kii =   $user->pluck('balance');

จากนั้นในบรรทัดถัดไปคุณสามารถสรุปได้ดังนี้:

$sum =  $kii->sum(); 

หวังว่าจะช่วยได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.