java - 按一定百分比均匀过滤列表 - Kotlin/Java
问题描述
我正在寻找一种在 Kotlin/Java 中最有效的方法来过滤List
一定百分比的元素,并且删除过滤的元素将以统一的方式应用于整个集合(即 - 要删除的元素跨越整个收集均匀);
例如
- 过滤以下 50%
[0,1,2,3,4,5,6,7,8,9] = [0,2,4,6,8]
- 过滤以下 10%
[1,100,1000,10000] = [1,100,10000]
我想出了以下 Kotlin 扩展函数,它在百分比 < 50% 且集合很大时效果很好,但是当集合 >50% 时,这种方法就失败了,因为它只处理整数除法。
private fun <E> List<E>.filterDownBy(perc: Int): List<E> {
val distro = this.size / ((perc * this.size) / 100)
if (perc == 0 || distro >= this.size)
return this
return this.filterIndexed { index, _ -> (index % distro) != 0 }
有没有更好的方法来做到这一点并且当百分比> 50%时也会起作用?
解决方案
我认为标准库中没有太多帮助,但我想出了这种“手动”方法:
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()
,但这并不合适,因为 lambda 必须使用和更新外部状态。)
推荐阅读
- jekyll - 设置的变量是否包括全局范围?如果是,有什么方法可以创建局部变量?
- c# - 使用 secp384r1 ECC 算法和 KDFX963 解密消息
- salesforce - 使用 SOQL 查询 Salesforce 对象列名称
- ggplot2 - 仅绘制具有 n 个计数的直方图
- mysql - 如果我要在单独的 docker 容器中使用 mysql,我是否需要 Spring Initializr 中的 mysql 依赖项?
- raspberry-pi - 为什么我的 RPi UART0 (ttyAMA0) 在禁用蓝牙时会死机?
- android - 设备重新启动(或类似状态)Android 时本地通知不显示
- mongodb - 在 phoenix/elixir 中使用 mongodb 驱动程序进行深度查询
- java - 为什么我得到 UNAUTHORIZED_DOMAIN:Domain 没有被项目列入白名单?
- angular - 部署和托管 Angular 前端和 Go 后端