Avatar billede JacoDK Nybegynder
12. august 2015 - 17:49 Der er 7 kommentarer og
1 løsning

Beregn total fra array() forældre/barn

Hej Eksperter,

Jeg har et array, som længe af drillet mig.

Mit array har et key ved navn "FolderValue" i alle array's, som indeholder en talværdi. Talværdien vil jeg gerne multipler til forældren. Et eksempel på dette


Niveau, Værdi, Total (beregnet),
Forældre, 1, 6
  Barn I, 2, 2
  Barn II, 3, 3

Altså vil jeg gene mit array multipler Forældre med værdien 1 sammen med Barn I med værdien 2 og Barn II med værdien 3. Dermed vil et regnestykke se således ud : 1+2+3 = 6, som opsummeres i totalen.

Mit array ser sådan her ud:
Array
(
    [1] => Array
        (
            [FolderName] => Mappe 1
            [FolderID] => 1
            [FolderParentID] =>
            [FolderValue] => 10
            [FolderTotal] =>
            [FolderChield] => Array
                (
                    [5] => Array
                        (
                            [FolderName] => Mappe 5
                            [FolderID] => 5
                            [FolderParentID] => 1
                            [FolderValue] => 0
                            [FolderTotal] =>
                            [FolderChield] => Array
                                (
                                    [9] => Array
                                        (
                                            [FolderName] => Mappe 8
                                            [FolderID] => 9
                                            [FolderParentID] => 5
                                            [FolderValue] => 10
                                            [FolderTotal] =>
                                        )

                                )

                        )

                )

        )

    [2] => Array
        (
            [FolderName] => Mappe 2
            [FolderID] => 2
            [FolderParentID] =>
            [FolderValue] => 0
            [FolderTotal] =>
            [FolderChield] => Array
                (
                    [3] => Array
                        (
                            [FolderName] => Mappe 3
                            [FolderID] => 3
                            [FolderParentID] => 2
                            [FolderValue] => 70
                            [FolderTotal] =>
                        )

                    [4] => Array
                        (
                            [FolderName] => Mappe 4
                            [FolderID] => 4
                            [FolderParentID] => 2
                            [FolderValue] => 0
                            [FolderTotal] =>
                        )

                    [6] => Array
                        (
                            [FolderName] => Mappe 6
                            [FolderID] => 6
                            [FolderParentID] => 2
                            [FolderValue] => 25
                            [FolderTotal] =>
                        )

                    [7] => Array
                        (
                            [FolderName] => Mappe 6
                            [FolderID] => 7
                            [FolderParentID] => 2
                            [FolderValue] => 0
                            [FolderTotal] =>
                            [FolderChield] => Array
                                (
                                    [8] => Array
                                        (
                                            [FolderName] => Undermappe 8
                                            [FolderID] => 8
                                            [FolderParentID] => 7
                                            [FolderValue] => 10
                                            [FolderTotal] =>
                                        )

                                )

                        )

                )

        )

    [10] => Array
        (
            [FolderName] => Dette er en ny hovedmappe
            [FolderID] => 10
            [FolderParentID] =>
            [FolderValue] => 0
            [FolderTotal] =>
        )

)


Jeg har prøvet med foreach, men kan ikke få den til at fungere rigtig... :(

        function summa( $input )
        {
            foreach( $input AS $tree => $value )
            {
                if ( is_array( $value ) )
                {
                    $input['FolderTotal'] += summa( $value );
                }
            }
            return $input['FolderTotal']+$input['FolderValue'];
        }


Håber der er et klogt hoved der kan løse den :)
Avatar billede JacoDK Nybegynder
13. august 2015 - 05:19 #1
Hermed et array der direkte kan anvendes i php:

$arr = array ( 1 => array ( 'FolderName' => 'Mappe 1', 'FolderID' => 1, 'FolderParentID' => NULL, 'FolderValue' => 10, 'FolderTotal' => 0, 'FolderChield' => array ( 5 => array ( 'FolderName' => 'Mappe 5', 'FolderID' => 5, 'FolderParentID' => 1, 'FolderValue' => 0, 'FolderTotal' => 0, 'FolderChield' => array ( 9 => array ( 'FolderName' => 'Mappe 8', 'FolderID' => 9, 'FolderParentID' => 5, 'FolderValue' => 10, 'FolderTotal' => 0, ), ), ), ), ), 2 => array ( 'FolderName' => 'Mappe 2', 'FolderID' => 2, 'FolderParentID' => NULL, 'FolderValue' => 0, 'FolderTotal' => 0, 'FolderChield' => array ( 3 => array ( 'FolderName' => 'Mappe 3', 'FolderID' => 3, 'FolderParentID' => 2, 'FolderValue' => 70, 'FolderTotal' => 0, ), 4 => array ( 'FolderName' => 'Mappe 4', 'FolderID' => 4, 'FolderParentID' => 2, 'FolderValue' => 0, 'FolderTotal' => 0, ), 6 => array ( 'FolderName' => 'Mappe 6', 'FolderID' => 6, 'FolderParentID' => 2, 'FolderValue' => 25, 'FolderTotal' => 0, ), 7 => array ( 'FolderName' => 'Mappe 6', 'FolderID' => 7, 'FolderParentID' => 2, 'FolderValue' => 0, 'FolderTotal' => 0, 'FolderChield' => array ( 8 => array ( 'FolderName' => 'Undermappe 8', 'FolderID' => 8, 'FolderParentID' => 7, 'FolderValue' => 10, 'FolderTotal' => 0, ), ), ), ), ), 10 => array ( 'FolderName' => 'Dette er en ny hovedmappe', 'FolderID' => 10, 'FolderParentID' => NULL, 'FolderValue' => 0, 'FolderTotal' => 0, ), )
Avatar billede JacoDK Nybegynder
13. august 2015 - 06:52 #2
Nu er jeg kommet frem til noget der ligner det jeg søger, men den regner forkert og har lidt børne-fejl :/

<?php /* START */

$arr = array ( 1 => array ( 'FolderName' => 'Mappe 1', 'FolderID' => 1, 'FolderParentID' => NULL, 'FolderValue' => 10, 'FolderTotal' => 0, 'FolderChield' => array ( 5 => array ( 'FolderName' => 'Mappe 5', 'FolderID' => 5, 'FolderParentID' => 1, 'FolderValue' => 0, 'FolderTotal' => 0, 'FolderChield' => array ( 9 => array ( 'FolderName' => 'Mappe 8', 'FolderID' => 9, 'FolderParentID' => 5, 'FolderValue' => 10, 'FolderTotal' => 0, ), ), ), ), ), 2 => array ( 'FolderName' => 'Mappe 2', 'FolderID' => 2, 'FolderParentID' => NULL, 'FolderValue' => 0, 'FolderTotal' => 0, 'FolderChield' => array ( 3 => array ( 'FolderName' => 'Mappe 3', 'FolderID' => 3, 'FolderParentID' => 2, 'FolderValue' => 70, 'FolderTotal' => 0, ), 4 => array ( 'FolderName' => 'Mappe 4', 'FolderID' => 4, 'FolderParentID' => 2, 'FolderValue' => 0, 'FolderTotal' => 0, ), 6 => array ( 'FolderName' => 'Mappe 6', 'FolderID' => 6, 'FolderParentID' => 2, 'FolderValue' => 25, 'FolderTotal' => 0, ), 7 => array ( 'FolderName' => 'Mappe 6', 'FolderID' => 7, 'FolderParentID' => 2, 'FolderValue' => 0, 'FolderTotal' => 0, 'FolderChield' => array ( 8 => array ( 'FolderName' => 'Undermappe 8', 'FolderID' => 8, 'FolderParentID' => 7, 'FolderValue' => 10, 'FolderTotal' => 0, ), ), ), ), ), 10 => array ( 'FolderName' => 'Dette er en ny hovedmappe', 'FolderID' => 10, 'FolderParentID' => NULL, 'FolderValue' => 0, 'FolderTotal' => 0, ), );

#    $output = '';
    function summa( $array )
    {
        global $output;
        $sum = 0;
        if ( is_array( $array ) )
        {
            foreach ( $array as $item )
            {
                if ( $item['FolderParentID'] )
                {
                                $sum += summa( $item['FolderChield'] ) + $item['FolderValue'];
                                $output[ $item['FolderParentID'] ]['FolderTotal'] =& $sum;
                            }
                        else
                            {
                                $sum += summa( $item['FolderChield'] ) + $item['FolderValue'];
                                $output[ $item['FolderID'] ]['FolderTotal'] =& $sum;
                            }
                 
                if ( $item['FolderChield'] )
                {
                    foreach ( $item['FolderChield'] as $subitem )
                                {
                                    #echo '<pre>'.print_r($subitem, true).'</pre>';
                                    $sum += summa( $subitem['FolderChield'] ) + $subitem['FolderValue'];
                        $output[ $subitem['FolderParentID'] ]['FolderChield'][ $subitem['FolderID'] ]['FolderTotal'] =& $sum;
                    }
                  }
            }
        }
        else return 0;
        #return $output;
    }

    $arr = summa( $arr );
    echo '<pre>'.print_r( $output , true).'</pre>';

/* END */ ?>


den kommer med følgende
Array
(
    [5] => Array
        (
            [FolderTotal] => 10
            [FolderChield] => Array
                (
                    [9] => Array
                        (
                            [FolderTotal] => 10
                        )

                )

        )

    [1] => Array
        (
            [FolderTotal] => 105
            [FolderChield] => Array
                (
                    [5] => Array
                        (
                            [FolderTotal] => 105
                        )

                )

        )

    [2] => Array
        (
            [FolderTotal] => 105
            [FolderChield] => Array
                (
                    [3] => Array
                        (
                            [FolderTotal] => 105
                        )

                    [4] => Array
                        (
                            [FolderTotal] => 105
                        )

                    [6] => Array
                        (
                            [FolderTotal] => 105
                        )

                    [7] => Array
                        (
                            [FolderTotal] => 105
                        )

                )

        )

    [7] => Array
        (
            [FolderTotal] => 10
            [FolderChield] => Array
                (
                    [8] => Array
                        (
                            [FolderTotal] => 105
                        )

                )

        )

    [10] => Array
        (
            [FolderTotal] => 105
        )

)


Kort fortalt er dette metoden, men der er fejl i den :(
Avatar billede olsensweb.dk Ekspert
13. august 2015 - 14:04 #3
lad det være sagt med det sammen, jeg er ikke den store hej til rekursive functioner.

ver 0 : bare for at vise man kommer ind i de rigtige array


<?php
include "array.php"; // det array du visser i #1
function summa($input, $level) {
    if ($level <= 0)  return;
    foreach ($input AS $key => $value) {
        echo "<br>";
        echo "her = " . ( $input[$key]['FolderTotal'] + $input[$key]['FolderValue'] );
        $folder_id = $input[$key]['FolderID']; // OK
        echo "<br>";
        echo "folder id = " . $folder_id;
        echo "<br>";
        if (isset($input[$key]['FolderChield'])) {
            summa($input[$key]['FolderChield'], $level - 1);
        }
    }
    return 0;
}

//echo summa($arr, 1);
//echo summa($arr, 2);
echo summa($arr, 5);
?>


istedet for at bruge global bør du kigge på call by reference
http://php.net/manual/en/language.references.pass.php
Avatar billede olsensweb.dk Ekspert
13. august 2015 - 17:11 #4
et lille eks med brug af call by ref, læg mærke til & tegnet foran $sum i parameteren i function's erklæringen

<?php
include "array.php";
function summa($input, &$sum) {
    foreach ($input AS $key => $value) {       
        $sum += $input[$key]['FolderValue'];               
        $folder_id = $input[$key]['FolderID'];

        echo "folder id = " . $folder_id;
        echo "<br>";
        if (isset($input[$key]['FolderChield'])) {
            summa($input[$key]['FolderChield'], $sum);
        }
    }
    //return $sum;
}

$total=0;
summa($arr, $total);
echo "<br>" . $total;
// echo summa($arr, $total);
?> 
Avatar billede JacoDK Nybegynder
15. august 2015 - 18:35 #5
Hej Ronols,

Tak for dine scripts. Jeg har prøvet dem af, og de er desværre ikke helt det jeg søger.

Jeg har dog kommet frem til følgende ud fra lidt sammensætning af metoder:

function summa( $array, $FolderLevel=0 )
    {
        global $output, $outputBuffer, $FolderTotal;
        if ( is_array( $array ) )
        {
            foreach ( $array as $item )
            {
                summa( $item['FolderChield'], $FolderLevel );
#
#  Ovenstående fungere med at opsummere totalen, men outputter ikke undermapperne.
#
                        $FolderTotal += $item['FolderValue'];

                            if ( !isset($outputBuffer[ $folders['FolderID'] ]) )
                            {
                                # INSERT DATA TO ARRAY
                                $outputBuffer[ $item['FolderID'] ] = array_merge( array_slice($item, -count($item), count($item)-1), array('FolderLevel' => $FolderLevel, 'FolderTotal' => $FolderTotal));
                            }
                            if ( !empty( $item['FolderParentID'] ) )
                            {
                                # HAS NO PARENT ID
                                $outputBuffer[ $item['FolderParentID'] ]['FolderChield'][ $item['FolderID'] ] =& $outputBuffer[ $item['FolderID'] ];
                            }
                            else
                            {
                                # HAS A PARENT ID
                                $output[ $item['FolderID'] ] =& $outputBuffer[ $item['FolderID'] ];
                                $FolderTotal = 0;
                            }
            }
                        $FolderLevel = 0;
        }
        else return $outputBuffer;
}


Dette giver dog kun output af Niveau 0 mapper, og medtager ikke undermapperne i Niveau 1, 2, 3, 4, .... etc.

Her er output jeg får fra ovenstående script, hvor totalen passer, men den outputter ikke undermapperne / child.
Array
(
    [1] => Array
        (
            [FolderName] => Mappe 1
            [FolderID] => 1
            [FolderParentID] =>
            [FolderValue] => 10
            [FolderTotal] => 20
            [FolderLevel] => 0
        )

    [2] => Array
        (
            [FolderName] => Mappe 2
            [FolderID] => 2
            [FolderParentID] =>
            [FolderValue] => 0
            [FolderTotal] => 105
            [FolderLevel] => 0
        )

    [10] => Array
        (
            [FolderName] => Dette er en ny hovedmappe
            [FolderID] => 10
            [FolderParentID] =>
            [FolderValue] => 0
            [FolderLevel] => 0
            [FolderTotal] => 0
        )

)
Avatar billede olsensweb.dk Ekspert
16. august 2015 - 11:15 #6
$FolderLevel burde være nemt !!
tæl op før du kalder summa, og tæl ned efter du kalder summa
og slet $FolderLevel = 0; i bunden inde i functionen
da $FolderLevel ikke skal bruges uden for functionen, og derved være en call by ref, (bruger ikke global) men beholde sin værdi inde i functionen, når den retunerer skal værdien være static

http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static

>function summa($array)
hvorfor er $array ikke et call by ref ??
du skal jo bruge det ændrede array uden for functionen
(call by ref, ved array spare også hukommelse, da man ikke skal kopiere hele array't over, men kun lave en referance)

   
function summa($array)
    {
        static $FolderLevel = 0;
       
       
        global $output, $outputBuffer, $FolderTotal;
        if ( is_array( $array ) )
        {
            foreach ( $array as $item )
            {
                $FolderLevel++;
                summa( $item['FolderChield'] );
                $FolderLevel--;

#
#  Ovenstående fungere med at opsummere totalen, men outputter ikke undermapperne.
#
                        $FolderTotal += $item['FolderValue'];

                            if ( !isset($outputBuffer[ $folders['FolderID'] ]) )
                            {
                                # INSERT DATA TO ARRAY
                                $outputBuffer[ $item['FolderID'] ] = array_merge( array_slice($item, -count($item), count($item)-1), array('FolderLevel' => $FolderLevel, 'FolderTotal' => $FolderTotal));
                            }
                            if ( !empty( $item['FolderParentID'] ) )
                            {
                                # HAS NO PARENT ID
                                $outputBuffer[ $item['FolderParentID'] ]['FolderChield'][ $item['FolderID'] ] =& $outputBuffer[ $item['FolderID'] ];
                            }
                            else
                            {
                                # HAS A PARENT ID
                                $output[ $item['FolderID'] ] =& $outputBuffer[ $item['FolderID'] ];
                                $FolderTotal = 0;
                            }
            }
                        // $FolderLevel = 0;
        }
        else return $outputBuffer;
}


jeg syntes jeg har brugt rigeligt tid på dette spm, og mangler friske indput fra andre, så jeg vil anbefale dig at lukke dette spm og oprette et nyt
Avatar billede JacoDK Nybegynder
16. august 2015 - 11:46 #7
Hej Ronols,

Tusind tak for din tid, og for at du har gjort dig umage med dine svar.

Jeg tror du har ret i at spørgsmålet bør lukkes. Jeg vurdere lige om det skal åbnes igen, men skal selvfølgelig nok poste en løsning, når jeg har fundet den :)

Igen skal du have tusind tak for din hjælp, og du må meget gerne lægge et svar.
Avatar billede olsensweb.dk Ekspert
17. august 2015 - 19:11 #8
du får et svar her
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester