在 Kotlin 中维护重复值的两个列表的交集

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

我想找到两个列表之间公共元素的数量而不消除重复项。

例如:


输入:

[1, 3, 3]
&
[4, 3, 3]

输出:

2
,因为共同元素是
[3, 3]


输入:

[1, 2, 3]
&
[4, 3, 3]

输出:

1
,因为共同元素是
[3]


如果我使用 Kotlin 集合 intersect,结果是一个集合,这将阻止我计算重复值。

我发现(对于Python)this,它以不同的方式处理重复项和this,这导致我使用this实现,其中

a
b
是列表:

val aCounts = a.groupingBy { it }.eachCount()
val bCounts = b.groupingBy { it }.eachCount()
var intersectionCount = 0;
for ((k, v) in aCounts) {
    intersectionCount += Math.min(v, bCounts.getOrDefault(k, 0))
}

但是,作为 Kotlin 的新手,我想知道是否有一种更“Kotlin-y”的方式来做到这一点——利用 Kotlin 的所有集合功能?也许是避免显式迭代的东西?

collections kotlin
3个回答
9
投票

这个:

val a = listOf(1, 2, 3, 3, 4, 5, 5, 5, 6)
val b = listOf(1, 3, 3, 3, 4, 4, 5, 6, 6, 7)

var counter = 0

a.intersect(b).forEach { x -> counter += listOf(a.count {it == x}, b.count {it == x}).min()!! }

println(counter)

将打印

6

它使用两个列表的交集,并通过迭代其每个项目,将两个列表中该项目的最小出现次数添加到计数器中。

通过此导入:

import kotlin.math.min

您可以避免在每次迭代时创建列表并简化为:

a.intersect(b).forEach { x-> counter += min(a.count {it == x}, b.count {it == x}) } 


感谢 Arjan,一种更优雅的计算总和的方法:

val result = a.intersect(b).map { x -> min(a.count {it == x}, b.count {it == x}) }.sum()

0
投票

从两个或多个数组列表中获取公共元素

输入

  • a = {1, 2, 2, 4, 5, 6}
  • b = {1, 2, 2, 4, 5, 6}
  • c = {1, 2, 2, 4, 6}

输出 = {1, 2, 2, 4, 6}

fun main() {

val array = ArrayList<ArrayList<String>>()

val arr1 = arrayListOf("1", "2", "2", "4", "5", "6")
val arr2 = arrayListOf("1", "2", "2", "4", "5", "6")
val arr3 = arrayListOf("1", "2", "2", "4", "6")

array.add(arr1)
array.add(arr2)
array.add(arr3)


println(getCommonElements(array)) }

创建一个数据类,用于存储arrayIndex和elementIndex

internal class IndexArray(val arrayIndex: Int,
                      val elementIndex: Int)

获取公共元素的算法

fun getCommonElements(arrayList: ArrayList<ArrayList<String>>): ArrayList<String> {

val commonElements = ArrayList<String>()
var isContain = true
val firstArray = arrayList[0]

val indexArray = ArrayList<IndexArray>()

// for loop for firstArray
for (e in firstArray) {

    var elementIndex: Int
    var arrayIndex: Int

    // for loop for next ArrayList
    for (i in 1 until arrayList.size) {

        if (!arrayList[i].contains(e)) {
            isContain = false
            break

        } else {
            elementIndex = arrayList[i].indexOf(e)
            arrayIndex = i

            indexArray.add(IndexArray(arrayIndex, elementIndex))
        }
    }

    if (isContain) {
        commonElements.add(e)

        // remove element
        for (i in 0 until indexArray.size) {
            arrayList[indexArray[i].arrayIndex].removeAt(indexArray[i].elementIndex)
        }

        indexArray.clear()

    } else {
        indexArray.clear()
        isContain = true
    }


}

return commonElements }

0
投票

输入

val a = listOf(1, 2, 3, 3, 4, 5, 5, 5, 6)
val b = listOf(1, 3, 3, 3, 4, 4, 5, 6, 6, 7)

从列表中创建两组。集合不允许有重复的元素

val setA = a.toSet()
val setB = b.toSet()

通过将两个集合相交来找到共同值

val intersection = setA.intersect(setB)

将集合转换为数组

return intersection.toIntArray()
© www.soinside.com 2019 - 2024. All rights reserved.