Java/Kotlin:通过类ID查找多个HashSet的交集

abithluo  于 2023-06-24  发布在  Kotlin
关注(0)|答案(4)|浏览(145)

我在查找包含数据类的散列集数组的交集时遇到了麻烦(我想通过标识符相交):

class Protein(val id: String, val score: Double, val molw: Double, val spc: Int)

我已经从. csv文件中提取了一些数据到这种类型的结构中:

ArrayList<HashSet<Protein>>

因此,我有六个数组列表[每个csv对应1个],每个列表包含一个散列集,其中包含数千个蛋白质结构。以下是我迄今为止尝试获得的基于公共www.example.com的交集HashSet Protein.id:

fun intersection(data: ArrayList<HashSet<Protein>>): HashSet<Protein> {

val intersectionSet = HashSet<Protein>(data[0])

for (i in 1..data.size) {
    intersectionSet.retainAll(data[i])
}
return intersectionSet
}

这将返回一个空列表,这是有意义的,因为它试图与Protein对象相交并将每个条件作为一个整体进行匹配。
如何调用data [i]. id作为交集条件?我对Kotlin和数据类还很陌生:)

tct7dpnv

tct7dpnv1#

为了简化给定的答案,可以使用apply

return data.reduce { acc, it -> acc.apply { retainAll(it) } }
wz1wpwve

wz1wpwve2#

如果您在Protein类中添加hashCodeequals函数的定义,如下所示,则HashSet将能够使用id字段适当地检查交集。

class Protein(val id: String, val score: Double, val molw: Double, val spc: Int) {
  override fun hashCode() = id.hashCode()
  override fun equals(other: Any?) = other?.let { id == (it as Protein).id } ?: false
}

此外,您可能希望将intersection函数内循环中的范围更改为1..(data.size-1)而不是1..data.size,以避免越界。或者,您可以将其功能编写如下:

fun intersection(data: ArrayList<HashSet<Protein>>): HashSet<Protein> {
  return data.reduce { acc, it -> acc.apply { retainAll(it) } }
}
rjee0c15

rjee0c153#

请注意,如果您不希望依赖于作为Hashset的输入,则可以执行以下操作:

fun <T> multiIntersect(data: Collection<Set<T>>) = 
    HashSet(data.minBy { it.size }!!).apply {  data.forEach { retainAll(it) } }

通过从最小的集合开始,您可以潜在地保存大量的运行时间,因为检索集合的大小可以在恒定的时间内完成,因为它保存在对象的字段中。

oprakyz7

oprakyz74#

下面是一些Kotlin的内置函数

infix fun <T> Array<out T>.intersect(
    other: Iterable<T>
): Set<T> (source)

infix fun ByteArray.intersect(
    other: Iterable<Byte>
): Set<Byte> (source)

infix fun ShortArray.intersect(
    other: Iterable<Short>
): Set<Short> (source)

infix fun IntArray.intersect(other: Iterable<Int>): Set<Int>
(source)
infix fun LongArray.intersect(
    other: Iterable<Long>
): Set<Long>(source)

infix fun FloatArray.intersect(
    other: Iterable<Float>
): Set<Float> (source)

infix fun DoubleArray.intersect(
    other: Iterable<Double>
): Set<Double> (source)

infix fun BooleanArray.intersect(
    other: Iterable<Boolean>
): Set<Boolean> (source)

infix fun CharArray.intersect(
    other: Iterable<Char>
): Set<Char> (source)

返回一个集,其中包含此数组和指定集合都包含的所有元素。
返回的集合保留原始数组的元素迭代顺序。

相关问题