Nette,从文本区域中提取数字以执行计算
Nette, extract numbers from a textarea to perform a Calculation
你好,我有这个问题,我想从 textarea1 中获取输入值,例如:第一行的“300pcs,200$”和“500pcs,400$”等等,以执行根据件数增加价格(我曾经将它与输入一起使用并且它有效,但我被告知我需要一个文本区域)。计算结果类似于:textarea2“300pcs,220$”和第 2 行“500pcs,540$”增加了适当的百分比。我的问题是,我需要从文本区域的每一行中提取数字来执行计算,但它似乎并没有像想象的那样工作。
declare(strict_types=1);
namespace App\Presenters;
use App\Forms\FormFactory;
use Nette\Application\UI\Form;
use Nette\Database\Context;
use Nette\Utils\ArrayHash;
class HomepagePresenter extends BasePresenter
{
/**
* @var Context
* @inject
*/
public $database;
/**
* @var FormFactory
* @inject
*/
public $formFactory;
protected function createComponentCalculationForm(): Form
{
$form = $this->formFactory->create();
$form->addSelect('supplier', 'Dodavatel:', $this->database->table('suppliers')->fetchPairs('id', 'supp_name'));
$form->addTextArea('user_input');
$form->addSubmit('calculate', 'Spočítat');
$form->addTextArea('result')
->setHtmlAttribute('class', 'totalPrice')
->setHtmlAttribute('readonly');
$form->onSuccess[] = function (Form $form, ArrayHash $values): void {
$selectedSupp = $values->supplier;
$userInput = $values->user_input;
$lines = $array = explode("\n", $userInput);
foreach ($lines as $line) {
preg_match_all('/[\d]+/', $line, $numbers);
list($quantity, $price) = $numbers[0];
}
$modifier = $this->database->fetch('SELECT percentage FROM prices WHERE supplier_id = ? AND max >= ? AND min <= ?', $selectedSupp, $quantity, $quantity);
$total = round($price + ($price / 100) * $modifier->percentage);
$form['result']->setValue("$quantity Ks, $total Kč + DPH");
};
return $form;
}
}
我的猜测是您可能希望编写边界较少的表达式,例如
(?i)(\d+)\s*pcs\s*[,;]*\s*$?\s*(\d+(?:\.\d*)?|(?:\.\d+))\s*$?
或者如果不是,对于问题中的相同格式,
(\d+)pcs,\s(\d+)$
可能只是工作。
Demo
为了测试,您可能需要编写一些函数并在您希望执行的循环中调用它,例如:
测试
$str = '
300pcs, 200$
301pcs, 201$
301pcs, 201.5$
301.2pcs, 201$
300pcs, 200$
500pcs, 400$
310pcs , 220.22$
550 PCS, 540.5$
301pcs 220.$
502 pcs, .54 $
303 PCS ; 0.6
504 pcs, 0.4
500 pcs, . $';
function extractPiecesPrices($str)
{
$re = '/^(\d+)pcs,\s(\d+)$$/m';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
foreach ($matches as $key => $value) {
if ($value[2] != "") {
print($value[2] . " is price\n");
// do some math on prices
}
if ($value[1] != "") {
print($value[1] . " is pcs\n");
// do some math on pieces
}
}
}
extractPiecesPrices($str);
输出
200 is price
300 is pcs
201 is price
301 is pcs
200 is price
300 is pcs
400 is price
500 is pcs
你好,我有这个问题,我想从 textarea1 中获取输入值,例如:第一行的“300pcs,200$”和“500pcs,400$”等等,以执行根据件数增加价格(我曾经将它与输入一起使用并且它有效,但我被告知我需要一个文本区域)。计算结果类似于:textarea2“300pcs,220$”和第 2 行“500pcs,540$”增加了适当的百分比。我的问题是,我需要从文本区域的每一行中提取数字来执行计算,但它似乎并没有像想象的那样工作。
declare(strict_types=1);
namespace App\Presenters;
use App\Forms\FormFactory;
use Nette\Application\UI\Form;
use Nette\Database\Context;
use Nette\Utils\ArrayHash;
class HomepagePresenter extends BasePresenter
{
/**
* @var Context
* @inject
*/
public $database;
/**
* @var FormFactory
* @inject
*/
public $formFactory;
protected function createComponentCalculationForm(): Form
{
$form = $this->formFactory->create();
$form->addSelect('supplier', 'Dodavatel:', $this->database->table('suppliers')->fetchPairs('id', 'supp_name'));
$form->addTextArea('user_input');
$form->addSubmit('calculate', 'Spočítat');
$form->addTextArea('result')
->setHtmlAttribute('class', 'totalPrice')
->setHtmlAttribute('readonly');
$form->onSuccess[] = function (Form $form, ArrayHash $values): void {
$selectedSupp = $values->supplier;
$userInput = $values->user_input;
$lines = $array = explode("\n", $userInput);
foreach ($lines as $line) {
preg_match_all('/[\d]+/', $line, $numbers);
list($quantity, $price) = $numbers[0];
}
$modifier = $this->database->fetch('SELECT percentage FROM prices WHERE supplier_id = ? AND max >= ? AND min <= ?', $selectedSupp, $quantity, $quantity);
$total = round($price + ($price / 100) * $modifier->percentage);
$form['result']->setValue("$quantity Ks, $total Kč + DPH");
};
return $form;
}
}
我的猜测是您可能希望编写边界较少的表达式,例如
(?i)(\d+)\s*pcs\s*[,;]*\s*$?\s*(\d+(?:\.\d*)?|(?:\.\d+))\s*$?
或者如果不是,对于问题中的相同格式,
(\d+)pcs,\s(\d+)$
可能只是工作。
Demo
为了测试,您可能需要编写一些函数并在您希望执行的循环中调用它,例如:
测试
$str = '
300pcs, 200$
301pcs, 201$
301pcs, 201.5$
301.2pcs, 201$
300pcs, 200$
500pcs, 400$
310pcs , 220.22$
550 PCS, 540.5$
301pcs 220.$
502 pcs, .54 $
303 PCS ; 0.6
504 pcs, 0.4
500 pcs, . $';
function extractPiecesPrices($str)
{
$re = '/^(\d+)pcs,\s(\d+)$$/m';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
foreach ($matches as $key => $value) {
if ($value[2] != "") {
print($value[2] . " is price\n");
// do some math on prices
}
if ($value[1] != "") {
print($value[1] . " is pcs\n");
// do some math on pieces
}
}
}
extractPiecesPrices($str);
输出
200 is price
300 is pcs
201 is price
301 is pcs
200 is price
300 is pcs
400 is price
500 is pcs