как группировать по родительскому массиву в foreach - PullRequest
0 голосов
/ 07 мая 2020

Как я могу добиться таких результатов. Я хочу сгруппировать данные по b_id, поэтому это моя попытка, но я не могу понять, вместо этого он продолжает отображать разгруппированные данные. ниже я перечислил код и результат, который я хочу и не хочу.

Тестовые данные

$d = "[
       {
          \"b_id\": 1,
          \"d\": 0,
          \"lo\": 10,
          \"m\": 4000,
          \"pts\": [
             {
                \"amount\": 3500,
                \"b_id\": 1,
                \"fid\": 2,
                \"side\": 2,
                \"user_id\": 27
             },
             {
                \"amount\": 3000,
                \"b_id\": 1,
                \"fid\": 2,
                \"side\": 1,
                \"user_id\": 27
             },
             {
                \"amount\": 2000,
                \"b_id\": 1,
                \"fid\": 2,
                \"side\": 2,
                \"user_id\": 20
             },
             {
                \"amount\": 1000,
                \"b_id\": 1,
                \"fid\": 2,
                \"side\": 1,
                \"user_id\": 20
             }
          ],
          \"ro\": 10,
          \"side\": 2,
          \"user_id\": 27,
          \"w\": 5000
       },
       {
          \"b_id\": 2,
          \"d\": 0,
          \"lo\": 10,
          \"m\": 6000,
          \"pts\": [
             {
                \"amount\": 4000,
                \"b_id\": 2,
                \"fid\": 2,
                \"side\": 1,
                \"user_id\": 27
             },
             {
                \"amount\": 2000,
                \"b_id\": 2,
                \"fid\": 2,
                \"side\": 2,
                \"user_id\": 27
             },
             {
                \"amount\": 1000,
                \"b_id\": 2,
                \"fid\": 2,
                \"side\": 2,
                \"user_id\": 20
             },
             {
                \"amount\": 2000,
                \"b_id\": 2,
                \"fid\": 2,
                \"side\": 1,
                \"user_id\": 20
             }
          ],
          \"ro\": 9,
          \"side\": 1,
          \"user_id\": 27,
          \"w\": 3000
       }
    ]";

Код

    $d = json_decode($d);
    foreach($d as $data => $row) {
        foreach($row as $a => $b) {
            if($a == "pts") {
                foreach($b as $col => $val) {
                    echo "======[START (b_id: ".$row->b_id."]======<br>";
                    $odds = getOdds($row->m,$row->lo,$row->ro);
                    $ret = getMax($val->amount,$odds);
                    $amount = round(abs($val->amount - $ret),2);

                    echo "Odds: $odds<br>";
                    echo "Ret: $ret<br>";
                    echo "Amount: $amount <br>";
                    echo "=======[END (b_id: ".$row->b_id."]=======<br><br>";
                }
            }
        }
    }


    function getOdds($bets,$a,$b) {
       return ($bets * $b) / $a;
    }

    function getMax($bet, $max) {
        global $bets;
        $ret = 0;

        if($bets < $max) {
            $bets += $bet;
            $ret = ($bets % $max);

            if($ret == $bets)
                $ret = 0;
        } else
            $ret = $bet;

        return $ret;
    }

результаты

        ======[START (b_id: 1]======
        Odds: 4000
        Ret: 0
        Amount: 3500
        =======[END (b_id: 1]=======

        ======[START (b_id: 1]======
        Odds: 4000
        Ret: 2500
        Amount: 500
        =======[END (b_id: 1]=======

        ======[START (b_id: 1]======
        Odds: 4000
        Ret: 2000
        Amount: 0
        =======[END (b_id: 1]=======

        ======[START (b_id: 1]======
        Odds: 4000
        Ret: 1000
        Amount: 0
        =======[END (b_id: 1]=======

        ======[START (b_id: 2]======
        Odds: 5400
        Ret: 4000
        Amount: 0
        =======[END (b_id: 2]=======

        ======[START (b_id: 2]======
        Odds: 5400
        Ret: 2000
        Amount: 0
        =======[END (b_id: 2]=======

        ======[START (b_id: 2]======
        Odds: 5400
        Ret: 1000
        Amount: 0
        =======[END (b_id: 2]=======

        ======[START (b_id: 2]======
        Odds: 5400
        Ret: 2000
        Amount: 0
        =======[END (b_id: 2]=======

Но мне нужны эти результаты

       ======[START (b_id: 1]======
        Odds: 4000
        Ret: 0
        Amount: 3500

        Odds: 4000
        Ret: 2500
        Amount: 500

        Odds: 4000
        Ret: 2000
        Amount: 0

        Odds: 4000
        Ret: 1000
        Amount: 0
        =======[END (b_id: 1]=======


        ======[START (b_id: 2]======
        Odds: 5400
        Ret: 4000
        Amount: 0

        Odds: 5400
        Ret: 2000
        Amount: 0

        Odds: 5400
        Ret: 1000
        Amount: 0

        Odds: 5400
        Ret: 2000
        Amount: 0
        =======[END (b_id: 2]=======

Возможно ли добиться такого результата в foreach? спасибо

Ответы [ 2 ]

1 голос
/ 07 мая 2020

Группировка возможна и требует лишь небольшого изменения в вашем коде.

Обратите внимание, что печать строк START и END перемещена за пределы foreach и просто в "if ($ a ==" pts ") {" и что дополнительный "
" был добавлен к печати строки Amount.

if($a == "pts") {
    echo "======[START (b_id: ".$row->b_id."]======<br>";
    foreach($b as $col => $val) {
        $odds = getOdds($row->m,$row->lo,$row->ro);
        $ret = getMax($val->amount,$odds);
        $amount = round(abs($val->amount - $ret),2);

        echo "Odds: $odds<br>";
        echo "Ret: $ret<br>";
        echo "Amount: $amount <br><br>";
    }
    echo "=======[END (b_id: ".$row->b_id."]=======<br><br>";
}
0 голосов
/ 07 мая 2020

Это может быть написано несколькими способами, но некоторые важные моменты:

  • Не просите php выполнить такое же вычисление во внутреннем l oop, когда это возможно. выполняется только один раз во внешнем l oop.
  • Мне нравится, чтобы обработка и компонент кода отображения были разделены как можно больше, поэтому внутренние данные l oop собираются, склеиваются и выталкиваются во внешний массив коллекций l oop, затем по завершении итерации склейте данные коллекций вместе. Это также предотвращает любые замыкающие / висящие теги разметки (<br>).
  • Вы можете позволить себе опустить условие if во вложенных циклах, и один из циклов может быть полностью удален. Используйте array_column(), чтобы изолировать данные $amount, потому что это единственные данные, с которыми вы действительно работаете.
  • Не используйте объявления global, если вы можете передать заданное значение в качестве параметра функции .

Код: ( Демо )

$break = "\n"; // <br>
$break2 = "\n\n";  // <br><br>

$collections = [];
foreach($d as $row) {
    $odds = getOdds($row->m, $row->lo, $row->ro);
    $collection = [];
    foreach(array_column($row->pts, 'amount') as $amount) {
        $ret = getMax($row->m, $amount, $odds);              // I am assuming that $row-m is supposed to be $bets
        $amount = round(abs($amount - $ret), 2);
        $collection[] = implode($break, ["Odds: {$odds}", "Ret: {$ret}", "Amount: {$amount}"]);
    }
    $collections[] = implode($break, [
        "======[START (b_id: {$row->b_id}]======",
        implode($break2, $collection),
        "=======[END (b_id: {$row->b_id}]=======",
    ]);
}
echo implode($break2, $collections);

Вывод:

======[START (b_id: 1]======
Odds: 4000
Ret: 3500
Amount: 0

Odds: 4000
Ret: 3000
Amount: 0

Odds: 4000
Ret: 2000
Amount: 0

Odds: 4000
Ret: 1000
Amount: 0
=======[END (b_id: 1]=======

======[START (b_id: 2]======
Odds: 5400
Ret: 4000
Amount: 0

Odds: 5400
Ret: 2000
Amount: 0

Odds: 5400
Ret: 1000
Amount: 0

Odds: 5400
Ret: 2000
Amount: 0
=======[END (b_id: 2]=======
...