list - Kotlin 从列表中获取 x 个元素,但首先删除最小的数字
问题描述
所以想象你有一堂课Product
。在这个类中,有一个mutablelistOf<Stock>()
. 该类Stock
包含两个属性:一个属性是quantity
stock has ,另一个是amount of stars
. mutabeListOf<Stock>()
按升序排序(列表中的amount of stars
第一个股票有 1 星,然后是 2,然后是 3...)。
现在有一个客户想要从 Product 列表中取出 5 件商品(客户减少了数量属性)。顾客应先从星数最少的Stock
物品中 取走。如上所述,星数最少的股票位于列表的开头。在客户拿走这 5 件商品后,Stock 对象的数量属性应该减少,并且当它的数量属性为 0 时,该对象应该从列表中删除。
另一种情况是没有足够的物品要带走(例如,客户想要 15 个物品,但总共有 10 个)。在这种情况下,应取最大金额(10),并退回客户取走的金额(例如,此处为 10)。
我知道如何删除这些项目,但是当我删除它们时,数量会低于 0,并且 for 循环不会“跳转”到下一个 Stockobject。
这是我目前的方法:Class Stock
class Stock(var quantity: Int, val stars: Int) {
init {
if (quantity < 0) quantity = 0
}
}
类 Product 和函数 takeItems:
class Product {
private val stockList = mutableListOf<Stock>()
val availableItems: Double
get() {
return stockList.map { it.quantity.toDouble() }.sum()
}
fun addStock(item: Stock) = stockList.add(item)
fun enoughItemsAvailable(itemQuantity: Int): Boolean = availableItems >= itemQuantity
// The function I am trying to create to take items out of the list
fun takeItems(quantity: Int): Int {
stockList.sortBy { it.stars }
var taken = 0
for (i in stockList.indices) {
if (stockList[i].quantity == 0) stockList.removeAt(i)
if (enoughItemsAvailable(quantity)) {
do {
stockList[i].quantity -= quantity
taken++
} while (stockList[i].quantity > 0 || taken != quantity)
} else {
// when there is not enough items to be taken
stockList.clear()
return quantity
}
}
return taken
}
我希望你们理解我的问题。我感谢每一个帮助!
解决方案
在您的代码中,您从列表中的第一个库存中获取全部请求的数量,即使这导致它的数量为负。我认为您应该 putstockList[i].quantity--
而不是stockList[i].quantity -= quantity
,因为您的策略似乎是一次删除一个。
此外,如果 Stock 为空,则循环中的第一行将删除它,然后下一部分开始从下一个 Stock 中删除,而无需先检查它是否为空。如果连续两只股票为空怎么办?所以第一个if
应该是while
.
IndexOutOfBoundsException
但是由于您在迭代其索引时从列表中删除,如果有任何项目被删除,您将到达。因此,您需要if (i >= stockList.size) break
在循环的开头添加。
您对是否有足够的项目来满足完整请求的检查可以移到循环之外,以避免一遍又一遍地重复检查该条件。
我认为一个更简单的策略是遍历列表,从每个列表中获取尽可能多的内容,Stock
直到您获取足够的列表或用尽列表。然后用一行删除列表中的空 Stocks。这样,您就不需要单独的逻辑分支来处理不足以满足请求的情况,并且您不需要单独检查任何 Stocks 是否已经为空。
fun takeItems(quantity: Int): Int {
stockList.sortBy { it.stars }
var taken = 0
for (stock in stockList) {
val toRemove = min(quantity - taken, stock.quantity)
taken += toRemove
stock.quantity -= toRemove
if (quantity == taken) break
}
stockList.removeAll { it.quantity == 0 }
return taken
}
顺便说一句,它看起来availableItems
应该是Int
,而不是Double
,因为它是项目的计数。它可以更有效地完成
val availableItems: Int
get() = stockList.sumBy(Stock::quantity)
因为 usingmap
每次访问此属性时都会创建一个新列表。
推荐阅读
- google-app-engine - 如何在部署阶段在 gitlab ci 中添加 .env 文件?
- c# - 静态属性 - 如何正确初始化它?
- mongodb - 如何将 Mongodb $lookup 包含为 Spring @Query("")
- javascript - 使用 javascript/jquery 将图像 SVG 转换为内联 SVG
- ruby - ruby 以变量为键访问哈希
- node.js - Gps 设备数据不可编辑
- android - 从以编程方式创建的文件夹中获取所有视频文件
- ruby-on-rails - 使用 webpack 部署到 Heroku 时预编译资产时出错
- jquery-ui - jquery ui select - 如何获取对原始选择元素的引用
- process - 程序如何与硬件设备一起工作