Я не думаю, что в стандартной библиотеке есть что-то, что может помочь, но я придумал этот «ручной» подход:
fun <T> List<T>.takeProportion(prop: Double): List<T> {
if (prop < 0 || prop > 1)
throw IllegalArgumentException("prop ($prop) must be between 0 and 1")
val result = ArrayList<T>()
var tally = 0.5
for (i in this) {
tally += prop
if (tally >= 1.0) {
result += i
tally -= 1
}
}
return result
}
Он использует своего рода способ распространения ошибок дляубедитесь, что значения берутся равномерно по всему списку и используют плавающую точку, чтобы она плавно справлялась с любой пропорцией от 0,0 (давая пустой список) до 1,0 (принимая каждый элемент).
(возможно, естьспособ сделать это, используя только целочисленную арифметику, но использование плавающей запятой, вероятно, проще для кодирования и понимания.)
(Возможно, вы могли бы сделать его более функциональным с помощью filter()
, но это не совсем уместнопотому что лямбда должна использовать и обновлять внешнее состояние.)