List 使用自定义相等函数减去Kotlin中的两个列表
我有两个列表,我想得到只包含第一个列表中不在第二个列表中的元素的列表。问题是,在进行减法时,我需要指定一个自定义的List 使用自定义相等函数减去Kotlin中的两个列表,list,data-structures,kotlin,List,Data Structures,Kotlin,我有两个列表,我想得到只包含第一个列表中不在第二个列表中的元素的列表。问题是,在进行减法时,我需要指定一个自定义的equal。假设我想使用列表项中的一个字段。让我们说一下id 我是这样实施的: list1.filter { log -> list2.none { it.id == log.id } } 或 有更好的方法吗?请注意,我无法为类设置新的equal方法。根据注释,没有内置的方法可以做到这一点。(可能不是出于任何根本原因;只是因为没有人看到需要。) 但是,您可以自己轻松添加一个。
equal
。假设我想使用列表项中的一个字段。让我们说一下id
我是这样实施的:
list1.filter { log -> list2.none { it.id == log.id } }
或
有更好的方法吗?请注意,我无法为类设置新的
equal
方法。根据注释,没有内置的方法可以做到这一点。(可能不是出于任何根本原因;只是因为没有人看到需要。)
但是,您可以自己轻松添加一个。例如,下面是您的第一个建议,转换为扩展功能:
fun <T, R> Collection<T>.minus(elements: Collection<T>, selector: (T) -> R?)
= filter{ t -> elements.none{ selector(it) == selector(t) } }
(可能有更高效的实现,但这说明了这个想法。)另一种方法
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) }
}
fun main(){
val list1=listOf(0,1,2,3,4,5)
val list2=listOf(2,3,4)
println(列表1.filterNotIn(列表2))
}
有趣的收藏。过滤器主题(收藏:收藏):收藏{
val set=collection.toSet()
返回filterNot{set.contains(it)}
}
输出:
[0,1,5]
您这样做是可以的,但是当列表变大时,您可能希望这样做:
您可以先将参考列表(list2
)设置为一个集合,从而提高流程的效率
val referenceIds = list2.distinctBy { it.id }.toSet()
list1.filter { it.id !in referenceIds }
背景:
检查元素是否包含时,最有可能使用的ArrayList
的时间复杂度为O(n)。因此,如果列表变大,则需要更长的时间
另一方面,当检查元素是否包含时,
HashSet
的时间复杂度为O(1)。因此,如果list2
变得更大,它不会变慢。看起来不错,你说的“更好”到底是什么意思?@m0skit0我希望找到Kotlin本机方法来做类似的事情,我的意思是定义一个equal
方法,仅在运行命令时使用。我理解,类似于将lambda传递给减号
进行比较。没有这样的事。您的案例不是常见案例,也就是说,通常您应该使用类的equals
,而不是您自己的equals
。我们可以简单地执行list1-list2
。参考:@bh4r4th请阅读问题:这是关于使用自定义相等函数减去集合的问题,stdlib仍然不支持该函数。 对象自然相等的减法在stdlib中已经存在很长时间了。是的,是的,明白了。有道理。
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) }
}
val referenceIds = list2.distinctBy { it.id }.toSet()
list1.filter { it.id !in referenceIds }