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),
],
];
}
如果您想了解我如何计算每个参与者每天需要支付的价格,请告诉我。如果需要,我可以进一步解释。
我目前正在研究一个可以分割金钱的计算器。例如,我和我的朋友去度假 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),
],
];
}
如果您想了解我如何计算每个参与者每天需要支付的价格,请告诉我。如果需要,我可以进一步解释。