[英]PHP - Find minimum value in an array and combine all possible numbers to reach a given sum
Not sure following scenario is belong to Knapsack Problem or Coin Change Approach. 不确定以下场景是否属于背包问题或硬币变更方法。 Would like to seek solution of this problem in PHP language. 想在PHP语言中寻求解决这个问题的方法。 Require simple solution because not understand some algorithms (text theory) provided from Internet. 需要简单的解决方案,因为不了解Internet提供的一些算法(文本理论)。
Given a Table (A) as following: 鉴于表(A)如下:
TABLE (A)
---------
Item | Name | Price ($)
-------- ------------ --------------
1 | Adidas | 35
2 | Nike Run | 70
3 | Puma | 100
4 | Nike | 85
5 | NB | 65
Result: 结果:
Item | Name | Price ($)
-------- ------------ --------------
1 | Adidas | 35
5 | NB | 65
3 | Puma | 100
Given another sample Table (B) as following: 给出另一个样本表(B)如下:
TABLE (B)
---------
Item | Name | Price ($)
-------- ------------ --------------
1 | Adidas | 5
2 | Nike Run | 35
3 | Puma | 110
4 | Nike | 65
5 | NB | 15
Result: 结果:
Item | Name | Price ($)
-------- ------------ --------------
2 | Nike Run | 35
4 | Nike | 65
3 | Puma | 110
Say table A is an associative array, let's call it $a. 假设表A是一个关联数组,我们称之为$ a。 To find the first combination that will be >= 200 do this: 要找到> = 200的第一个组合,请执行以下操作:
$rowsWithValueOver200 = array();
foreach($a as $value) {
foreach($a as $value2) {
// Make sure to ignore the value selected in the first loop.
if ($value2 == $value)
continue;
foreach($a as $value3) {
// Make sure to ignore the value selected in the first and second loop.
if ($value3 == $value)
continue;
if ($value3 == $value2)
continue;
$total = $value3['Price'] + $value2['Price'] + $value['Price'];
if ($total >= 200) {
// Store all of the rows in the new array.
$rowsWithValueOver200[] = $value;
$rowsWithValueOver200[] = $value2;
$rowsWithValueOver200[] = $value3;
break;
}
}
}
}
So we iterate through the array 3 times. 所以我们遍历数组3次。 Check the sum once we're looking at 3 unique values. 一旦我们查看3个唯一值,请检查总和。 All the time making sure that we don't include the previously selected array element ($value or $value2). 始终确保我们不包含先前选择的数组元素($ value或$ value2)。 This could certainly be cleaned up a little and made more universal, but it'll work for 3 elements. 这肯定可以稍微清理一下并且更加通用,但它适用于3个元素。 A refactor of this into a more universal function would make recursive calls to itself, allow for a start position (then use a for loop instead of foreach). 将其重构为更通用的函数将对其自身进行递归调用,允许起始位置(然后使用for循环而不是foreach)。
To find the minimum value is pretty simple. 找到最小值非常简单。
$minVal = PHP_INT_MAX; // Initially something high, here it is the maximum integer value.
$minRow;
foreach($rowsWithValueOver200 as $value) {
if ($value['Price'] < $minVal){
$minVal = $value['Price'];
$minRow = $value;
}
}
Set your minimum value (minVal) to check against to something really high. 设置最小值(minVal)以检查真正高的值。 Iterate through the array values and if the $value['Price'] is less than the current minVal, then it is now the minVal and store the array element in $minRow for later reference. 迭代数组值,如果$ value ['Price']小于当前的minVal,那么它现在是minVal并将数组元素存储在$ minRow中供以后参考。
3 and 4 I'm not sure what you're asking. 3和4我不确定你在问什么。 It's not clear. 目前尚不清楚。 If you want to find the sum of the three rows in $rowsWithValueOver200 then you could just use what I had in the first answer. 如果你想在$ rowsWithValueOver200中找到三行的总和,那么你可以使用我在第一个答案中的内容。 If you want to do it with just the 3 final elements then do this: 如果你想只用3个最终元素来做,那么这样做:
$total = 0;
foreach($rowsWithValueOver200 as $value) {
$total += $value['Price'];
}
If you're looking for other possibilities that sum up to 200 or more then just use the first example, but instead of a foreach at the first loop use a for loop with an index. 如果您正在寻找总计200或更多的其他可能性,那么只需使用第一个示例,但在第一个循环中使用带有索引的for循环而不是foreach。 Start at each index. 从每个索引开始。
Good luck! 祝好运!
MySQL is properly equip to accomplish this all on its own. MySQL可以通过适当的方式完成所有这些工作。 You could pull your entire table for PHP to figure out, but this can get expensive on resources, and it most definitely will produce slower results, especially with larger databases. 你可以把你的整个表拉成PHP来弄清楚,但这可能会使资源变得昂贵,而且肯定会产生较慢的结果,特别是对于较大的数据库。 PHP usually needs to loop through the data several times to do enough array manipulation which MySQL can accomplish very easily. PHP通常需要多次遍历数据以进行足够的数组操作,MySQL可以很容易地完成。
Assuming your database looks like this: 假设您的数据库如下所示:
CREATE TABLE IF NOT EXISTS `A` (
`Item` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(10) NOT NULL,
`Price` decimal(10,2) NOT NULL,
PRIMARY KEY (`Item`),
UNIQUE KEY `Name` (`Name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
INSERT INTO `A` (`Item`, `Name`, `Price`) VALUES
(1, 'Adidas', '35.00'),
(2, 'Nike Run', '70.00'),
(3, 'Puma', '100.00'),
(4, 'Nike', '85.00'),
(5, 'NB', '65.00');
You can query it like so: 您可以这样查询:
SELECT @leastprice := min(`Price`) FROM `A`;
SELECT t1.Name AS Name1, t2.Name AS Name2, t3.Name AS Name3,
t1.Price AS Price1, t2.Price AS Price2, t3.Price AS Price3,
(t1.Price+t2.Price+t3.Price) AS `Total`
FROM `A` t1
LEFT JOIN `A` t2 ON t1.Item != t2.Item
LEFT JOIN `A` t3 ON t1.Item != t2.Item AND t2.Item != t3.Item
WHERE t1.price = @leastprice
AND t2.price<=t3.price
AND t1.price+t2.price+t3.price >= 200;
Result: 结果:
CREATE TABLE IF NOT EXISTS `B` ( `Item` int(10) unsigned NOT NULL AUTO_INCREMENT, `Name` varchar(10) NOT NULL, `Price` decimal(10,2) NOT NULL, PRIMARY KEY (`Item`), UNIQUE KEY `Name` (`Name`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ; INSERT INTO `B` (`Item`, `Name`, `Price`) VALUES (1, 'Adidas', '5.00'), (2, 'Nike Run', '35.00'), (3, 'Puma', '110.00'), (4, 'Nike', '65.00'), (5, 'NB', '15.00');
You can query it like so: 您可以这样查询:
SELECT @leastTalliablePrice := min(t1.Price) FROM `B` t1 LEFT JOIN `B` t2 ON t1.Item != t2.Item LEFT JOIN `B` t3 ON t1.Item != t2.Item AND t2.Item != t3.Item WHERE t2.price<=t3.price AND t1.price+t2.price+t3.price >= 200; SELECT t1.Name AS Name1, t2.Name AS Name2, t3.Name AS Name3, t1.Price AS Price1, t2.Price AS Price2, t3.Price AS Price3, (t1.Price+t2.Price+t3.Price) AS `Total` FROM `B` t1 LEFT JOIN `B` t2 ON t1.Item != t2.Item LEFT JOIN `B` t3 ON t1.Item != t2.Item AND t2.Item != t3.Item WHERE t1.price = @leastTalliablePrice AND t2.price <= t3.price AND t1.price+t2.price+t3.price >= 200;
Result: 结果:
If for some reason your database doesn't have 3 or more distinct items, or their prices aren't enough to reach your desired total, the query would simply return 0 rows in the same manner that a SELECT results 0 rows if it can't find any rows to select. 如果由于某种原因,您的数据库没有3个或更多不同的项目,或者它们的价格不足以达到您想要的总数,那么查询将以与SELECT结果0行相同的方式返回0行,如果它可以'找到要选择的行。 But if there were more than one match in the above case, it would result multiple rows like as the case in my first screenshot. 但是如果在上面的情况下有多个匹配,则会产生多行,就像我的第一个屏幕截图中的情况一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.