Як разлічыць працуе ўсяго ў масіве. PHP

У мяне ёсць масіў, які, напрыклад, выглядае наступным чынам:

$cases = array(23, 18, 5, 8, 10, 16);

Тое, што я хачу выхад быць гэта працуе ўсяго:

23, 41, 46, 54, 64, 80

Інфармацыя, якая можа дапамагчы растлумачыць: Гэты масіў у сапраўдны момант запаўняе лінейны графік, і мая мэта складаецца ў тым, каб паспрабаваць дадаць радок, якая паказвае сукупны прагрэс кожны дзень. (Дадзеныя паступаюць з БД, так што я не магу проста змяніць зыходны масіў)

2
Вы, па меншай меры што-небудзь паспрабаваў сябе? Якая была праблема, калі вы спрабавалі? Дзе вы затрымаліся?
дададзена аўтар PeeHaa, крыніца
На якую частку вы затрымаліся?
дададзена аўтар PeeHaa, крыніца
Логіка PHP для перабору масіва і папаўняецца агульнай складанасці.
дададзена аўтар user2448754, крыніца

8 адказы

Самы просты спосаб, з O (N) складанасці:

$original = array(23, 18, 5, 8, 10, 16);

$total = array();
$runningSum = 0;

foreach ($original as $number) {
    $runningSum += $number;
    $total[] = $runningSum;
}

var_dump($total);
10
дададзена
+1. Падручнік прыклад :)
дададзена аўтар Ja͢ck, крыніца
Ясна, проста, і вы ініцыялізуюцца зменныя правільна. :) Калі ваш зыходны спіс не з'яўляецца вялізным або адкрытым итератором, гэта нашмат больш эфектыўна, чым рашэнні итератора/генератара, як у выкананні і чытальнасці (= эфектыўнасці тэхнічнага абслугоўвання)
дададзена аўтар IMSoP, крыніца
+1 карысталіся, што (-:
дададзена аўтар ncm, крыніца
Дзякуючы атрымалася вельмі лёгка ажыццявіць гэта ў мой код
дададзена аўтар user2448754, крыніца

Трохі радок з кодам <> array_map . Ён перабірае масіў, павялічваючы фактычную агульную суму і вяртае яе.

$actual_sum = 0;
$running_total = array_map(function ($entry) use (&$actual_sum) { return $actual_sum += $entry; }, $cases);
7
дададзена
@IMSoP добра, змянілася.
дададзена аўтар bwoebi, крыніца
@Jack Ці з'яўляецца гэта праблемай? <�Код> $ undefined_val + = $ значэнне не будзе падымаць апавяшчэнне.
дададзена аўтар bwoebi, крыніца
@imsiso Так, я бачыў іх, я проста не заўважыў храналагічны парадак першага; Вось чаму я быў зьбянтэжаны.
дададзена аўтар bwoebi, крыніца
<�Код> $ actual_sum не вызначаны ў самым пачатку.
дададзена аўтар Ja͢ck, крыніца
Не, гэта не праблема; ён будзе працаваць, не падымаючы апавяшчэння ... гэта педантычны рэч, я думаю :)
дададзена аўтар Ja͢ck, крыніца
@jack не з'яўляецца праблемай, як гэта заяўлена ў выкарыстанні лініі, так што на самой справе вызначаецца (і ініцыялізуецца як нуль, калі гэта не было раней) у дэкларацыі. Гэта дзіўная справа, але гэта працуе ...
дададзена аўтар ircmaxell, крыніца
Хех, вось чаму мне не падабаецца выбар РНР пра тое, калі падняць апавяшчэння - гэта менавіта тая сітуацыя, дзе вы заўсёды павінны ініцыялізаваць ў зыходнае значэнне 0; у адваротным выпадку, калі гэтая лінія заканчваецца ўнутры цыклу, вы атрымаеце таямніча высокія значэння, пераменная атрымлівае праводзіцца на працягу ад папярэдняга выкліку.
дададзена аўтар IMSoP, крыніца
goooooooooooood
дададзена аўтар ncm, крыніца
OK спадзяюся, што вы заўважылі ў каментарах пад адказ @PhilCross «s. Я збіраюся выдаліць свой адказ, а таксама паставіць свой upvote (+1) на ваш адказ. што таксама дакладна.
дададзена аўтар ncm, крыніца

Уводзячы ў RunningTotalIterator рашэнне, у асноўным напісаная, каб дапоўніць іншыя адказы:

class RunningTotalIterator extends ArrayIterator
{
    private $sum;

    public function rewind()
    {
        parent::rewind();
        $this->sum = $this->valid() ? parent::current() : 0;
    }

    public function current()
    {
        return $this->sum;
    }

    public function next()
    {
        parent::next();
        if ($this->valid()) {
            $this->sum += parent::current();
        }
    }
}

$result = iterator_to_array(new RunningTotalIterator(array(23, 18, 5, 8, 10, 16)));
print_r($result);
4
дададзена
@ircmaxell Гэта праўда, яна была наўмысна пакінута з-за пустой масіў дасць пусты масіў ... выклік бягучы() на пусты итератор не вызначаны альбо AFAIK ... але я буду змяніць яго, тым не менш :)
дададзена аўтар Ja͢ck, крыніца
рэдагавання выглядае добра. Але гэта магчыма ў выпадку, калі я змяніць итератор (незаходимое значэнне, напрыклад) ...
дададзена аўтар ircmaxell, крыніца
У вас ёсць патэнцыйная лагічная памылка, дзе перамотка назад можа вырабіць недапушчальную суму. Замест гэтага ўсталюйце яго ў 0 да , калі $ this-> сапраўдны() праверыць у перамотцы() або ў іншае аддзяленне, ...
дададзена аўтар ircmaxell, крыніца

Выкарыстанне генератараў (новы 5,5 функцый):

function getRunningTotal(array $array) {
    $generator = function(array $array) {
        $total = 0;
        foreach ($array as $key => $value) {
            $total += $value;
            yield $key => $total;
        }
    };
    return iterator_to_array($generator($array));
}

Калі вы хочаце захаваць вынік у якасці итератора, проста вяртае $ генератара ($ масіў) непасрэдна ...

Як гэта працуе, з'яўляецца тое, што рухавік ўнутры стварае генератар (які дзейнічае як итератор), што «вяртае» усё, што далі. Такім чынам, захоўваючы уласны нарастаючы вынік ўнутры функцыі, мы можам «выхад» яго назад да абанента. Даволі прама наперад ...

4
дададзена
@Jack больш партатыўныя ... ircmaxell пераканаў мяне ў тым, што мы проста не можам капіяваць ўставіць яго без зменаў, калі мы хочам, каб перабраць яго, хачу яго як масіў і г.д.
дададзена аўтар bwoebi, крыніца
+1. (@NikiC павінен быў бы напісаць гэта) мне вельмі падабаецца гэты падыход, па меншай меры, таму што гэта не занадта вялікі і партатыўны.
дададзена аўтар bwoebi, крыніца
@bwoebi не занадта вялікі, ды (таму што генератары літаральна итератор shorteners) ... партатыўны (у параўнанні з поўнымі ўзарваны итераторами), спрэчна, калі вы маеце на ўвазе прасцей скапіяваць і ўставіць ;-)
дададзена аўтар Ja͢ck, крыніца

array_sum() would return the total of all numbers in the array added, however if you want a running total, here go:

$total = array();
$original = array(23, 18, 5, 8, 10, 16);

foreach($original as $number)
{
    $total[] = array_sum($total)+$number;
}

print_r($total);
3
дададзена
<�Код> $ за ўсё [] = array_sum ($ за ўсё) + $ лік; павінен быць хутчэй і карацей.
дададзена аўтар bwoebi, крыніца
Неверагодна! Абноўлены, спрошчаны!
дададзена аўтар Phil Cross, крыніца
Мае асноўныя навыкі матэматыка коціцца ўніз!
дададзена аўтар Phil Cross, крыніца
Ваша права ... Я прапусціў з закрывае фігурнай дужкі.
дададзена аўтар Phil Cross, крыніца
Гэта значна больш эфектыўна за ўсё выкарыстоўваць прамежкавы $ сума зменную замест паўторна рабіць array_sum() .
дададзена аўтар Ja͢ck, крыніца
$cases = array(23, 18, 5, 8, 10, 16);
$running = array_reduce(
    $cases,
    function ($counter, $value) {
        static $summer = 0;
        $summer += $value;
        $counter[] = $summer;
        return $counter;
    },
    array()
);

var_dump($running);
2
дададзена
Вы б ужо далі больш просты адказ, я проста нагадвае чытач, што PHP мае вялікі набор функцый,
дададзена аўтар Mark Baker, крыніца
Я не downvote яго, як гэта не так, але гэта больш злоўжыванне функцыі array_reduce чым з дапамогай іншай адпаведнай функцыі тут.
дададзена аўтар bwoebi, крыніца
ооо, як складана: о Гэта магчыма, але на самой справе занадта шмат інструкцыяў для маленькай задачы.
дададзена аўтар bwoebi, крыніца

Aaaaand іншы варыянт з array_walk , які ІМХО з'яўляецца найбольш натуральным:

$cases = array(23, 18, 5, 8, 10, 16);
$totals = array();
array_walk($cases, function($v) use (&$totals) {$totals[] = end($totals) + $v;});

See it in action.

2
дададзена
<?
$total = array();
$points = array(23, 18, 5, 8, 10, 16);

while ($points) {
 $total[] = array_shift($points);
 echo 'point: '.array_sum($total);
}
?>
1
дададзена