PHP 从具有正值和负值的数组中拆分钱

PHP split money from arrays with positive and negative values

我目前正在研究一个可以分割金钱的计算器。例如,我和我的朋友去度假 5 天。每个人都为团队付出一些,但并不是每个人都在那里整整 5 天。一个朋友在那里只有两天,另一个是三天,另外两个是 4 天,其余的每天都在那里。我已经到了我知道谁得到多少钱以及谁需要支付多少钱的部分。现在我“只”需要弄清楚谁需要用最少的交易支付给谁。我有一组正数:

40 => 68.25($)
42 => 44.25($)
49 => 28.75($)
41 => 24.25($)

和一个负数数组:

50 => -80.5($)
48 => -57.5($)
43 => -27.5($)

这些数组的键就是id。所以我知道哪个值属于哪个朋友。正数应该得到支付,负数需要支付。如果您对每个数组的值求和,您会得到相同的结果,除了负数组的总和显然是负数。

我现在的问题是如何获得交易,以便最终每个人都能得到或支付正确的金额?

提前感谢您的想法。

在我看来,最好更改您的数据结构,因为它只能由您或输入这些数据的人读取,我建议使用的是将您当前的结构更改为如下所示:

$transactions = [
    [
        "day" => "1",
        "made by" => "Awat",
        "cost" => "68.25"
    ],...
]

如果你看看这个,现在每个人都可以阅读并有更好的理解,你也可以计算出更好的方法,因为现在你可以在天[]之前获得你需要的任何信息 或者谁进行了这笔交易?

所以,为了更好地理解这一点,我为您创建了一个简单的计算,请记住我以最简单的方式创建了这个示例希望您能理解这一切,如果您遇到困难请告诉我,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Stack25</title>
</head>
<body>


<?php

$transactions = [
    [
        "day" => "1",
        "made by" => "Awat",
        "cost" => "68.25"
    ],
    [
        "day" => "2",
        "made by" => "Chitter",
        "cost" => "44.25"
    ],
    [
        "day" => "3",
        "made by" => "Awat",
        "cost" => "28.75"
    ],
    [
        "day" => "4",
        "made by" => "Chitter",
        "cost" => "24.25"
    ],
    [
        "day" => "5",
        "made by" => "Chitter",
        "cost" => "-80.5"
    ],
    [
        "day" => "6",
        "made by" => "Awat",
        "cost" => "-57.5"
    ],
    [
        "day" => "7",
        "made by" => "Awat",
        "cost" => "-27.5"
    ]
];


echo "<pre>The structure of my array:\n\n";
print_r($transactions);
echo "</pre>";


$totalCostP = 0;
$totalCostN = 0;

$awatCostP = 0;
$awatCostN = 0;

$chitterCostP = 0;
$chitterCostN = 0;

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

    // Cal
    if ($value['made by'] === "Awat"){

        // IS IT SPEND OR GAIN?
        // - = SPEND
        // + = GAIN
        if ($value['cost'] > 0){
            $awatCostP += floatval($value['cost']);
            $totalCostP += floatval($value['cost']);
        }else{
            $awatCostN += floatval($value['cost']);
            $totalCostN += floatval($value['cost']);
        }

    }

    if ($value['made by'] === "Chitter"){
        if ($value['cost'] > 0){
            $chitterCostP += floatval($value['cost']);
            $totalCostP += floatval($value['cost']);
        }else{
            $chitterCostN += floatval($value['cost']);
            $totalCostN += floatval($value['cost']);
        }
    }

}


echo "<h1>Awat has positive Balance: ".$awatCostP."</h1>";
echo "<h1>Awat has negative Balance: ".$awatCostN."</h1>";
echo "<h1>Awat total Balance: ".($awatCostP - ($awatCostN * -1))."</h1>";

echo "<hr>";

echo "<h1>Chitter has positive Balance: ".$chitterCostP."</h1>";
echo "<h1>Chitter has negative Balance: ".$chitterCostN."</h1>";
echo "<h1>Chitter total Balance: ".($chitterCostP - ($chitterCostN * -1))."</h1>";

echo "<hr>";

echo "<h1>Total positive Balance: ".$totalCostP."</h1>";
echo "<h1>Total negative Balance: ".$totalCostN."</h1>";

?>

</body>
</html>

注意:最后一点是,如果你的数据,我不推荐使用数组,最好存储在数据库中

您可以使用循环来务实地完成它。

<?php
$a1 = [2 => 10, 1 => 5];
$a2 = [2 => 9, 1=> -2];
$a3 = $a1;

foreach($a2 as $k => $v) {
    if(array_key_exists($k, $a3)) {
       $a3[$k] += $v;
    } else {
       $a3[$k] = $v; 
    }
}

print_r($a3);
exit();

输出

Array
(
    [2] => 19
    [1] => 3
)

我想出来给感兴趣的大家看。

$transactions = [];

try {
  foreach ($positives as $positive_participant_id => $positive) {
    foreach ($negatives as $negative_participant_id => $negative) {
      $rest = $positive - $negative * -1;

      if ($rest == 0) {
        // In this case the positive has received enough and negative has paid everything.
        $this->addTransaction($transactions, $negative_participant_id, $positive_participant_id, $positive);
        unset($positives[$positive_participant_id]);
        unset($negatives[$negative_participant_id]);
        break;
      }
      elseif ($rest < 0) {
        // In this case the positive has received enough.
        $this->addTransaction($transactions, $negative_participant_id, $positive_participant_id, $positive);
        $negatives[$negative_participant_id] = $rest;
        unset($positives[$positive_participant_id]);
        break;
      }
      elseif ($rest > 0) {
        // In this case the positive has not received enough but negative has paid everything.
        $this->addTransaction($transactions, $negative_participant_id, $positive_participant_id, $negative * -1);
        $positives[$positive_participant_id] = $rest;
        $positive = $rest;
        unset($negatives[$negative_participant_id]);
      }
      else {
        throw new \UnexpectedValueException("Rest value ($rest) in transaction calculation is an unexpected value.");
      }
    }
  }
}
catch (\UnexpectedValueException $e) {
  $this->logger->error($e->getMessage());
}

elseif ($rest < 0) 中的 unset 是不必要的,但在调试时它帮助我看到了还有多少正数。 transactions 数组包含有关参与者的更多信息(姓名、日期和价格)。我不确定这个解决方案是否有最少的交易,但它对我有用。它也不是最漂亮的解决方案。因此,如果您有任何改进,请告诉我。

private function addTransaction(array &$transactions, $sender, $receiver, $amount) {
  $transactions[] = [
    'sender' => [
      'participant' => $this->calculatorStorage->getParticipantById($sender),
      'price' => $amount,
    ],
    'receiver' => [
      'participant' => $this->calculatorStorage->getParticipantById($receiver),
    ],
  ];
}

如果您想了解我如何计算每个参与者每天需要支付的价格,请告诉我。如果需要,我可以进一步解释。