按一定百分比均匀地过滤列表 - 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必须使用和更新外部状态。

最新更新