在Kotlin / Java中将列表过滤到特定大小

时间:2019-06-06 22:57:53

标签: java kotlin collections

我正在寻找Kotlin / Java中最有效的方法,以一定数量过滤List,并删除以统一方式应用于集合的过滤元素(即-元素将其均匀地移到整个集合中);

例如

  • 将以下内容过滤到5 [0,1,2,3,4,5,6,7,8,9] = [0,2,4,6,8]

    < / li>
  • 将以下内容过滤到2 [[1,100,1000,10000] = [1,1000]

我想出了以下Kotlin扩展功能,但未按预期工作(返回的值超出了请求的数量-例如,初始大小= 2593,newcount = 125-list = 130)

fun <T> List<T>.filterDownByToCount(newCount: Int): List<T> {
    if (newCount < 0 || newCount >= this.size)
        throw IllegalArgumentException("prop ($newCount) must be between 1 and $newCount")
    val ratio = size / newCount
    val list = this.filterIndexed { index, _ -> index % ratio == 0 }
    return list
}

理想情况下,此函数可以处理从0list.size-1的任何内容,并且我想使用库来执行此操作(如果可能),但似乎找不到适合我的用例的任何内容。

2 个答案:

答案 0 :(得分:1)

问题在于size / newCount是比率的底值,因此比率太小,因此获得的元素比预期的多。

改为使用天花板

val ratio = (size + newCount - 1) / newCount

以您的示例为例,这将产生大小为124的列表。

答案 1 :(得分:1)

问题在于比率实际上是一个小数,但是您正在执行整数运算。

fun <T> List<T>.filterDownByToCount(newCount: Int): List<T> {
    if (newCount < 0 || newCount >= this.size)
        throw IllegalArgumentException("prop ($newCount) must be between 1 and $newCount")
    val ratio = size.toDouble() / newCount
    var accu = 0.0
    val list = this.filter { _ ->
        (accu <= 0).also { if (accu <= 0) accu += ratio; accu-- }
    }
    return list
}

您可以将比率更改为Double-在您的示例中,这将返回125元素的结果。