用php实现数组的连续演绎

nzkunb0c  于 2023-06-21  发布在  PHP
关注(0)|答案(1)|浏览(79)

我从数据库中得到这个数组值

#    amount   deduction
[0]   50        10
[1]   300       20
[2]   200       30

我想对这些数组进行递归演绎,直到数据为零,然后如果数组的第一个数量为零(0),则演绎将添加到下一个数据,然后如果第二个数量为零(0),则第一次和第二次演绎将添加到第三个数量,依此类推,直到所有数量都为零(0)。但如果第三个金额为零(0),则应将扣除额添加到第二个扣除额中。

[0]          [1]          [2]
50  - 10     300 - 20     200 - 30
40  - 10     280 - 20     170 - 30
30  - 10     260 - 20     140 - 30
20  - 10     240 - 20     110 - 30
10  - 10     220 - 20      80 - 30
 0           200 - 30      50 - 30
             170 - 30      20 - 30
             140 - 30       0 -  0
             110 - 60
              50 - 60
               0

这是我的代码

$data = json_decode($debtsData, true);
$continue = true;
while($continue) {
    $continue = max(array_column($data, 'amount')) > 0;
    for($i=0; $i<count($data); ++$i) {
        $totalInterest = $data[$i]['interest_rate'] / 100;
        $periods = 12;
        $monthly = $data[$i]['monthly'];
        $_new_balance = !isset($data[$i]['done']) ? max($data[$i]['amount'], 0) : '';
        $interestPayment = ($totalInterest / $periods ) * $_new_balance;

        if($data[$i]['amount'] <= 0 && !isset($data[$i]['done'])) {
          $data[$i]['done'] = true;
          if(isset($data[$i+1])) {
             $data[$i+1]['monthly'] += $data[$i]['monthly'];
          }
        }

        echo !isset($data[$i]['done']) ? '$'.number_format(max($data[$i]['amount'], 0),2) : '';
        echo !isset($data[$i]['done']) ? '$'.number_format($data[$i]['monthly'],2) : '';
        echo !isset($data[$i]['done']) ? '$'.number_format($interestPayment,2).' ' : '';

        $data[$i]['amount'] -= $data[$i]['monthly'] - $interestPayment ;
     }
}

我的代码的问题是,如果我的第三个金额将结束零(0)比第二个金额,它不会添加到第二个扣除。

  • PS:只是不要介意我的代码中的兴趣变量 *
7gyucuyw

7gyucuyw1#

目前还不清楚索引2完成时的逻辑是什么-它应该尝试向后1(从索引21),还是向前直到它达到未完成的值(从索引20,但索引0已经完成,因此01)。
无论如何,问题代码中的具体问题是因为它只试图向上索引:

if(isset($data[$i+1])) {
    $data[$i+1]['monthly'] += $data[$i]['monthly'];
}

将该逻辑分离到getNextKey()函数中可能是有意义的,这样您就可以确定那里的逻辑。类似于:

function getNextKey($array, $i) {
    if (isset($array[$i+1]) && !$array[$i+1]['done']) {
        return $i+1;
    } else if (isset($array[$i-1]) && !$array[$i-1]['done']) {
        return $i-1;
    }

    // in this case, both the next and previous indices are already done, so the calculation is complete
    return -1;
}

$continue = max(array_column($data, 'amount')) > 0;应该在for循环之后,而不是之前。否则,当一切都已经为0时,您将以一个额外的迭代结束。
同样不清楚的是,余数在哪一点转移到下一个索引。在这个例子中,在第5步中,index 0计算为0,所以我认为在该步中,该金额将被添加到index 1的计算中。但在本例中似乎并非如此,因此您需要一个单独的变量来跟踪下一个循环的结转。
为了澄清,请看10 - 10的步骤。下一步是将10添加到索引1的余数中。但是,为什么当索引220 - 30时,它需要两步才能结转到索引1的余数呢?不清楚0 - 0在这里表示什么,因为我希望前面的步骤确定它“完成”。例如,我期望140 - 60,而不是140 - 30然后110 - 60
无论如何,这是我认为基于我上面所做的假设的工作版本:https://3v4l.org/OGU3u

<?php

$array = [
    0=>[
        'amount' => 50,
        'deduction' => 10
    ],
    1=>[
        'amount' => 300,
        'deduction' => 20
    ],
    2=>[
        'amount' => 200,
        'deduction' => 30
    ]
];

$finalArray = [];

foreach($array as $key => $val) {
    $array[$key]['done'] = false; // keep track of which values are done
    $array[$key]['remainder'] = 0; // carry over from other calculations
}

$continue = true;
while ($continue) {
    // reset remainders (calculated at the end of this step)
    $nextRemainders = array_fill(0, 3, 0);
    
    for($i=0; $i<count($array); $i++) {
        // skip already-completed arrays
        if ($array[$i]['done'] == true) {
            continue;
        }
        
        $subtract = $array[$i]['deduction'] + $array[$i]['remainder'];
        
        // for debugging
        $key = $array[$i]['amount'] . ' - ' . $subtract; 
        
        if ($array[$i]['amount'] > $subtract) {
            // subtract the deduction and remainder
            $array[$i]['amount'] -= $subtract;
            
            // append calculation to our final array
            $finalArray[$i][$key] = $array[$i]['amount'];
        } else {
            $array[$i]['done'] = true;
            
            // set this value to 0 even if the calculation would leave it negative
            $array[$i]['amount'] = 0;
            
            // append calculation to our final array so we can track the steps
            $finalArray[$i][$key] = $array[$i]['amount'];
            
            $nextKey = getNextKey($array, $i);
            
            // no more values to calculate, done!
            if ($nextKey !== -1) {
                // add this deduction to the next step's calculation
                $nextRemainders[$nextKey] += $array[$i]['deduction'];
            }
        }
    }
    
    // check next remainders here and apply to the next step
    for($j=0; $j<count($nextRemainders); $j++) {
        $array[$j]['remainder'] += $nextRemainders[$j];
    }
    
    $continue = max(array_column($array, 'amount')) > 0;
}

function getNextKey($array, $i) {
    if (isset($array[$i+1]) && !$array[$i+1]['done']) {
        return $i+1;
    } else if (isset($array[$i-1]) && !$array[$i-1]['done']) {
        return $i-1;
    }
    
    return -1;
}

print_r($finalArray);

其具有以下计算:

Array
(
    [0] => Array
        (
            [50 - 10] => 40
            [40 - 10] => 30
            [30 - 10] => 20
            [20 - 10] => 10
            [10 - 10] => 0
        )

    [1] => Array
        (
            [300 - 20] => 280
            [280 - 20] => 260
            [260 - 20] => 240
            [240 - 20] => 220
            [220 - 20] => 200
            [200 - 30] => 170
            [170 - 30] => 140
            [140 - 60] => 80
            [80 - 60] => 20
            [20 - 60] => 0
        )

    [2] => Array
        (
            [200 - 30] => 170
            [170 - 30] => 140
            [140 - 30] => 110
            [110 - 30] => 80
            [80 - 30] => 50
            [50 - 30] => 20
            [20 - 30] => 0
        )
)

相关问题