Kotlin фильтрация коллекция

Имею два массива целых чисел: Первый (неправильный) Wrongarray: 1, 5, 2, 7, 93, 8, 9, 3 Второй (правильный) Rightarray: 1, 2, 7, 8, 9, 3 По условию мне необходимо из первого массива убрать числа, которые превышают сумму соседних элементов (это 5 и 93 - тут просто). Решил сделать через коллекции Kotlin с предикатом. Формирую код:

val array = arrayOf(WrongArray)
val result = array.dropWhile { it < (it-1) + (it+1) }

Т.е. оставляю число, которое меньше суммы соседних чисел.Код

Компилятор выдает ошибки на логическую операцию. Что не так делаю?


Ответы (3 шт):

Автор решения: Alex_Skvortsov

Нет, без цикла по индексам Вам тут не обойтись.

Решить можно, например, так:

val wrongArray = listOf(1, 5, 2, 7, 93, 8, 9, 3)
val result = mutableListOf<Int>()
for (i in wrongArray.indices){
    when {
        i == 0 -> result.add(wrongArray[i])
        i == wrongArray.size - 1 -> result.add(wrongArray[i])
        wrongArray[i-1] + wrongArray[i+1] >= wrongArray[i] -> result.add(wrongArray[i])
    }
}
println(result)

Первый и последний элемент здесь попадают в результат в любом случае.

По поводу dropWhile. Из документации:

Returns a list containing all elements except first element that satisfy the given [predicate].

То есть dropWhile удалит первый элемент, не соответствующий условию.

Так как it - это сам элемент, а не итератор, условие it < (it-1) + (it+1) ВСЕГДА истинно, а значит Ваш код просто удалит первый элемент из списка.

P.s. На случай, если Вам нужно фильтровать список до тех пор, пока хоть один элемент превышает сумму соседей, то можно использовать такой код:

    val wrongArray = listOf(1, 5, 2, 7, 50, 93, 8, 9, 3)
    var pair = Pair(wrongArray, false)
    while (!pair.second) {
        pair = filter(pair.first)
    }
    println(pair.first)

Где filter:

fun filter(wrongArray: List<Int>): Pair<List<Int>, Boolean> {
    val result = mutableListOf<Int>()
    for (i in wrongArray.indices) {
        when {
            i == 0 -> result.add(wrongArray[i])
            i == wrongArray.size - 1 -> result.add(wrongArray[i])
            wrongArray[i - 1] + wrongArray[i + 1] >= wrongArray[i] -> result.add(wrongArray[i])
        }
    }
    return Pair(result, result.size == wrongArray.size)
}
→ Ссылка
Автор решения: Ziens

Можно и с предикатом

val array = intArrayOf(1, 5, 2, 7, 93, 8, 9, 3)

val filtered = array.filterIndexed { index, i ->
    when (index) {
        0, array.lastIndex -> true // Сохраняем первый и последний
        else -> i < array[index - 1] + array[index + 1]
    }
}.toTypedArray()

println(filtered.contentToString())

Вывод: [1, 2, 7, 8, 9, 3]

UPD: Даже ещё упростить можно:

array.filterIndexed { index, i -> (index == 0 || index == array.lastIndex) || i < array[index - 1] + array[index + 1] }

→ Ссылка
Автор решения: Дмитрий

Реализовал с самым простым вариантом и он работает (спасибо за поддержку, такие вещи в документации сразу не найдешь):

    val array = WrongArray.filterIndexed { index, i -> (index == 0 || index == WrongArray.lastIndex) || i < WrongArray[index - 1] + WrongArray[index + 1] }

return array.toIntArray()
→ Ссылка