使用自定义功能等于减去两个列表中科特林

问题描述 投票:2回答:3

我有两个列表,我想仅包含第一个列表中没有的第二个元素的列表。问题是,我需要指定一个自定义的equal减去时。让我们假设我想用在列表中的条目的领域之一。比方说,id

我实现了这种方式:

list1.filter { log -> list2.none { it.id == log.id } }

要么

val projection = logEntries.map { it.id }
list1.filter { it.id !in projection }

有没有更好的办法做到这一点?请考虑,我不能设置为类新equal方法帐户。

list data-structures kotlin
3个回答
3
投票

你的方式做到这一点是确定的,但是当列表变得更大,你可能想要做的是:

你可以使这个过程更有效,首先把你的参考列表(list2)一组。

val referenceIds = list2.distinctBy { it.id }.toSet()

list1.filter { it.id !in referenceIds }

背景:

你最有可能使用的ArrayList有O(n)的时间复杂度,当你检查元素是否包含。所以,如果列表变得更大,它会需要更长的时间。

在另一方面甲HashSet具有(1)当检查如果一个元件被包含的O一个时间复杂度。所以,如果list2变大也不会变慢。


1
投票

另一种方法?

fun main() {

    val list1 = listOf(0, 1, 2, 3, 4, 5)
    val list2 = listOf(2,3,4)

    println(list1.filterNotIn(list2))
}

fun <T> Collection<T>.filterNotIn(collection: Collection<T>): Collection<T> {
    val set = collection.toSet()
    return filterNot { set.contains(it) }
}

输出:[0, 1, 5]


0
投票

按照意见,有没有内置的方式做到这一点。 (可能不是任何根本的原因,只是因为没有人认为有必要。)

但是,您可以轻松地自己添加一个。例如,这里是你的第一个建议,转化为扩展功能:

fun <T, R> Collection<T>.minus(elements: Collection<T>, selector: (T) -> R?)
    = filter{ t -> elements.none{ selector(it) == selector(t) } }

然后,您可以以同样的方式,一个内置的功能将工作称之为:

list1.minus(list2){ it.id }

(可能有更有效的实现,但是这说明了想法。)

© www.soinside.com 2019 - 2024. All rights reserved.