Как отфильтровать список на месте с Kotlin?

В Java я могу удалить элементы из списка с помощью этого кода:

private void filterList(List<Item> items) {
    Iterator<Item> iterator = items.iterator();
    while (iterator.hasNext()) {
        if (checkItem(iterator.next())) {
            iterator.remove();
        }
    }
}

Как сделать то же самое в Котлине (т.е. удалить некоторые элементы в List без повторного создания)?

Ответ 1

Просто используйте .retainAll {... } или .removeAll {... }, оба принимающие предикат, чтобы отфильтровать его на месте:

items.retainAll { shouldRetain(it) }

items.removeAll { shouldRemove(it) }

Обратите внимание, что items должны быть MutableList<T> для этого, а не только List<T>, который является только для чтения список в Котлин и, таким образом, не возникает никаких мутирует функций (см: Коллекции в справочнике по языку).

Кстати, эти две функции эффективно реализованы для списков, поддерживающих произвольный доступ: тогда список не уплотняется после удаления каждого элемента (в худшем случае время O (n 2)), и вместо этого элементы перемещаются в списке как он обрабатывается, давая время O (n).


И если вы не хотите изменять исходный список, вы можете создать отдельную коллекцию, в которой будут .filter {... } только те элементы, которые вы хотите сохранить, используя .filter {... } или .filterNot {... }, это будет работать для чтения- только List<T>:

val filtered = items.filter { shouldRetain(it) }

val filtered = items.filterNot { shouldRemove(it) }

Ответ 2

В Kotlin есть много опрятных встроенных функций. Вы можете попробовать использовать filter здесь.

val filteredItems = items.filter { checkItem(it) }  

К сожалению, он воссоздает список. Этот API был разработан специально, чтобы избежать дополнительной изменчивости.

Но если вы все еще хотите использовать метод MutableList, используйте метод retainAll

items.retainAll { checkItem(it) }

Ответ 3

Это удалит четные числа из списка 1-9 и напечатает [1, 3, 5, 7, 9]

var myLists = mutableListOf(1,2,3,4,5,6,7,8,9)
myLists.removeAll{ it % 2 == 0 }
println(myLists)

Это сохранит четные числа и удалит остальные из списка 1-9, а также напечатает [2, 4, 6, 8]

myLists = mutableListOf(1,2,3,4,5,6,7,8,9)
myLists.retainAll{ it % 2 == 0 }
println(myLists)

Попробуйте их в https://play.kotlinlang.org/