从kotlin中另一个列表中的对象更新列表中的对象

从kotlin中另一个列表中的对象更新列表中的对象,kotlin,Kotlin,有没有更好的方法来写以下内容: private fun updateImportantProperty( firstList: List<MyObjectX>?, secondList: List<MyObjectX>? ) { firstList?.forEach { item1 -> secondList?.forEach { item2 -> if (relatesInSomeWayToEa

有没有更好的方法来写以下内容:

private fun updateImportantProperty(
    firstList: List<MyObjectX>?,
    secondList: List<MyObjectX>?
) {
    firstList?.forEach { item1 ->
        secondList?.forEach { item2 ->
            if (relatesInSomeWayToEachOther(item1, item2)) {
                item1.importantProperty = item2.importantProperty
            }
        }
    }
}
private fun updateImportantProperty(
第一个列表:列表?,
第二名单:名单?
) {
firstList?.forEach{item1->
第二个列表?.forEach{item2->
如果(以某种方式与另一项(第1项、第2项)相关){
item1.importantProperty=item2.importantProperty
}
}
}
}
上述代码的结果可能是更新了firstList的1个对象,或者更新了7个对象(如果列表共有7个对象)


我只想更新firstList中对象的一个重要属性。假设列表中没有任何内容,例如分类或大小,或者如果所有对象都在两个列表中。可读性是我所追求的。

如果列表变大,对第一个列表中的每个项目在整个第二个列表中进行迭代会变慢,因为这需要
O(n^2)
时间

如果匹配项很少(即第一个列表中的每个项不会有很多匹配项,只有少数匹配项),您可能希望通过从第二个列表的所有项中提取对彼此相关的真正有意义的内容,然后快速查找第一个列表的每个项,来构建某种索引

例如:

val secondListIndex = secondList.groupBy { getIndexKey(it) }

firstList.forEach { item1 ->
    val matchingSecondListItems = secondListLookup[getLookupKey(item1)].orEmpty()
    matchingSecondListItems.forEach { item2 ->
        item1.importantProperty = item2.importantProperty
    }
}

我在这里使用了两个函数,
getIndexKey
getLookupKey
,但是如果匹配条件很简单,那么这可能是相同的函数

假设
Map
没有意义,并且正如您提到的,时间复杂性不是问题,我将只关注如何在可读性方面改进代码

尽管如此,我还是要介绍性能方面的一些改进,即如果第二个列表为空/
null
,则不必调用
firstList.forEach
。此外,由于这似乎是一个非常特殊的用例,我宁愿为它添加一个扩展函数,以便更清楚地知道哪个列表是由什么更新的,例如:

fun List<MyObjectX>.updateBy(other: List<MyObjectX>?) {
  if (other != null && other.isNotEmpty())
    forEach { thisItem ->
      other.filter { relatesInSomeWayToEachOther(thisItem, it) }
           .forEach { thisItem.importantProperty = it.importantProperty }
    }
}
fun List.updateBy(其他:List?){
if(other!=null&&other.isNotEmpty())
forEach{thisItem->
other.filter{relatesinsomewaytoeachher(thisItem,it)}
.forEach{thisItem.importantProperty=it.importantProperty}
}
}
因此,我认为使用它更具可读性,例如:

val oneNullable : List<MyObjectX>? = ...
val twoNotNull : List<MyObjectX>? = ...

oneNullable?.updateBy(twoNotNull)
// or vice-versa
twoNotNull.updateBy(oneNullable)
val-oneNullable:列表?=。。。
val twoNotNull:列表?=。。。
oneNullable?.updateBy(twoNotNull)
//反之亦然
twoNotNull.updateBy(oneNullable)
关于,内部循环发生轻微变化时最多应更新的对象:

fun List<MyObjectX>.updateOnceBy(other: List<MyObjectX>?) {
  if (other != null && other.isNotEmpty()))
    forEach { thisItem ->
      other.firstOrNull { 
        relatesInSomeWayToEachOther(thisItem, it)
      }?.also {
        thisItem.importantProperty = it.importantProperty
      }
    }
}
fun List.updateOnceBy(其他:列表?){
if(other!=null&&other.isNotEmpty())
forEach{thisItem->
其他.firstOrNull{
以某种方式与其他项(此项,it)关联
}?还有{
thisItem.importantProperty=it.importantProperty
}
}
}
嗯。。。我懂了。。。我认为调用方的可读性高于实现方;-)

也许将其拆分有助于提高可读性:

fun MyObjectX.updateBy(other: List<MyObjectX>) {
  other.filter { this == it } // or if only first applies, firstOrNull again
       .forEach { importantProperty = it.importantProperty }
}

fun List<MyObjectX>.updateBy(other: List<MyObjectX>?) {
  if (other != null && other.isNotEmpty())
    forEach {
      it.updateBy(other)
    }
}
fun MyObjectX.updateBy(其他:列表){
other.filter{this==it}//或者如果仅第一次应用,请再次使用firstOrNull
.forEach{importantProperty=it.importantProperty}
}
有趣的列表。更新比(其他:列表?){
if(other!=null&&other.isNotEmpty())
弗雷奇{
it.updateBy(其他)
}
}

但是我认为类似于
映射的东西不仅可以提高时间复杂度,而且还可以提高可读性…

因此,您基本上希望通过将某些属性值替换为第二个列表中最后匹配的属性来映射第一个列表。如果您能提供更多的上下文,当然会更容易,但我将尝试简化您的语法:

firstList?.map { 
  firstListElement -> secondList
    ?.filter { it.relatesInSomeWayTo(firstListElement) }
    ?.lastOrNull()
    ?.let { firstListElement.copy(property = it.property) }
      ?: firstListElement 
}
我相信这将是更科特林的方式

请注意还有两个可选的调整-首先,您的“relatesTo”函数应该是MyObjectX上的扩展函数。其次,它应该是不可变的,因此,使用copy而不是赋值属性

编辑:
对不起,那不能编译
filter
函数返回列表,而不是对象,因此需要添加
lastOrNull()
调用。固定的;)

一个用于循环,询问第一个列表是否包含另一个,然后根据位置更新它可能是一个愚蠢的问题,但是
importantProperty
equals()
方法的一部分吗?如果是这样,您可能希望反转
If
条件,否则如果
If(item1==item2)
item1.importantProperty==item2.importantProperty
则该代码不可用,对吗?那么你想做什么?@Adam但是代码就更没有意义了。。。如果
item1
item2
是同一个对象,它们的
importantProperty
的值怎么可能不同?哦,是啊,对不起,我绊倒了,它们不是同一个对象,importantProperty不是equals的一部分!不寻求运行时间优化。可读性为王,我们正在寻找一些整洁的kotlin收集函数,或者两个可以在没有两个
forEach
es和一个
if
的情况下实现这一点的函数。我想额头痛是很明显的