Равномерно отфильтровать список на определенный процент - Kotlin / Java - PullRequest
1 голос
/ 02 июня 2019

Я ищу наиболее эффективный способ в 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%?

1 Ответ

2 голосов
/ 03 июня 2019

Я не думаю, что в стандартной библиотеке есть что-то, что может помочь, но я придумал этот «ручной» подход:

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(), но это не совсем уместнопотому что лямбда должна использовать и обновлять внешнее состояние.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...