如何根据 kotlin/java 中的另一个列表过滤列表?

Lun*_*lpo 14 list filter kotlin

我有两种类型FooApiFooModel

class FooApi (var aId) 
class FooModel(var mId)
Run Code Online (Sandbox Code Playgroud)

是一种简化以下FooModel基于FooApi列表过滤列表的功能的方法:

fun f(fooModelList: List<FooModel>, fooApiList: List<FooApi>) : List<FooModel> {
  return fooModelList.filter { fooApiList.map { it.aId }.contains ( it.mId ) }
}
Run Code Online (Sandbox Code Playgroud)

Rol*_*and 11

对我来说看起来没问题。我只会改变一些小东西(虽然不是必需的),所以它最终会像下面这样:

 fun List<FooModel>.f(fooApiList: List<FooApi>) = filter { m -> fooApiList.any { it.aId == m.mId } }
Run Code Online (Sandbox Code Playgroud)

我这样做的一些原因:

  • 我认为过滤总是应用于一个列表 FooModels,对吗?(这就是扩展函数将类型缩小到 的原因List<FooModel>
  • 您对 fooApiList 的映射对象不感兴趣,所以这就是我使用的原因 any;还有一个好处是,现在比较的两个值彼此相邻
  • 总结一切可以说得那么容易,你甚至可以省略方法体(因此返回类型、返回语句等)

尽管如此,这与您所做的几乎相同......只是少了一点代码和重新排列......顺便调用它看起来像:

val listA : List<FooModel> = TODO()
val listB : List<FooApi> = TODO()

val containedList = listA.f(listB)
Run Code Online (Sandbox Code Playgroud)

如果您更频繁地需要这样的构造,也许以下更通用的解决方案会有所帮助:

fun <T, U> List<T>.intersect(uList: List<U>, filterPredicate : (T, U) -> Boolean) = filter { m -> uList.any { filterPredicate(m, it)} }
Run Code Online (Sandbox Code Playgroud)

然后你也可以使用它:

val containedList = listA.intersect(listB) {
    a, b -> a.aId == b.mId
}
Run Code Online (Sandbox Code Playgroud)

那么你的f再次可能看起来就像:

fun List<FooModel>.f(fooApiList: List<FooApi>) = intersect(fooApiList) { a, b ->  a.mId == b.aId }
Run Code Online (Sandbox Code Playgroud)


Maj*_*ard 6

我会做类似的事情

val apiList = listOf(FooApi(1), FooApi(2), FooApi(3))
val modelList = listOf(FooModel(1), FooModel(3))

val output = apiList.flatMap { api -> modelList.filter { api.id == it.id }}
Run Code Online (Sandbox Code Playgroud)

给定作为输出

[FooModel(id=1), FooModel(id=3)]

不知道区别大不大...