流式传输两个集合并根据公共属性收集地图

发布于 2025-02-13 05:05:08 字数 1168 浏览 0 评论 0原文

我环顾四周,但没有找到优雅的解决方案。我要做的是有一个很好的简化(双关语意图)解决方案,以从具有1个共享属性的两个集合(ID)中创建一个地图。地图应为匹配对象的键值。

我暂时完成的工作是集合1上的一个foreach,在集合2上的foreach中以获取匹配模型,然后对其进行操作。我想创建地图,然后单独对地图中的每个对进行操作。我试图提出一个简单的例子,以使其更加清楚。

data class FirstNameModel(val idNumber: String, val firstName: String)
data class LastNameModel(val idNumber: String, val lastName: String)

val randomFirstNameList = listOf(
   FirstNameModel("5631ab", "Bob"),
   FirstNameModel("ca790a", "George"),
   FirstNameModel("j8f1sa", "Alice")
)

val randomLastNameList = listOf(
   LastNameModel("j8f1sa", "Smith"),
   LastNameModel("5631ab", "Johnson"),
   LastNameModel("ca790a", "Takai")
)

// stream function to correctly create map (not just a null one like below).

val map: Map<FirstNameModel, LastNameModel>? = null

fun printIt() {
   map?.forEach {
       println("Name for id ${it.key.idNumber} is ${it.key.firstName} ${it.value.lastName}")
   }
//    should print something like:
//            Name for id 5631ab is Bob Johnson
//            Name for id ca790a is George Takai
//            Name for id j8f1sa is Alice Smith
}

我目前一直在Kotlin尝试过此操作,但这是我有时在Java中的用例,所以对这两者都感到好奇。

I have looked around a bit but have not found a elegant solution. What I am trying to do is have a nice streamlined (pun intended) solution to create a map from two collections who have 1 shared property (an id of sorts). The map should be key-value of the matching objects.

How I have done it for now is a forEach on collection 1 and within a forEach on collection 2 to get the matching model and then do an operation on it. I would like to create the map and then separately just do the operation on every pair in the map. I have tried to come up with a simple example to make it a bit more clear.

data class FirstNameModel(val idNumber: String, val firstName: String)
data class LastNameModel(val idNumber: String, val lastName: String)

val randomFirstNameList = listOf(
   FirstNameModel("5631ab", "Bob"),
   FirstNameModel("ca790a", "George"),
   FirstNameModel("j8f1sa", "Alice")
)

val randomLastNameList = listOf(
   LastNameModel("j8f1sa", "Smith"),
   LastNameModel("5631ab", "Johnson"),
   LastNameModel("ca790a", "Takai")
)

// stream function to correctly create map (not just a null one like below).

val map: Map<FirstNameModel, LastNameModel>? = null

fun printIt() {
   map?.forEach {
       println("Name for id ${it.key.idNumber} is ${it.key.firstName} ${it.value.lastName}")
   }
//    should print something like:
//            Name for id 5631ab is Bob Johnson
//            Name for id ca790a is George Takai
//            Name for id j8f1sa is Alice Smith
}

I have been trying this in Kotlin for now but it's a use case I sometimes also have in Java, so am curious for both.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梅窗月明清似水 2025-02-20 05:05:10

这将起作用,包括 @扫地机(谢谢!)中提到的案例下面的评论:

val map: Map<FirstNameModel, LastNameModel> = randomFirstNameList.map { it.idNumber }
  .plus(randomLastNameList.map { it.idNumber })
  .distinct()
  .associate { idNumber ->
    (randomFirstNameList.firstOrNull { it.idNumber == idNumber } ?: FirstNameModel(idNumber, "")) to
    (randomLastNameList.firstOrNull { it.idNumber == idNumber } ?: LastNameModel(idNumber, ""))
  }

但是,引入数据类以保持结果很有意义:

data class NameModel(val idNumber: String, val firstName: String, val lastName: String)

val map: List<NameModel> = randomFirstNameList.map { it.idNumber }
  .plus(randomLastNameList.map { it.idNumber })
  .distinct()
  .map { idNumber ->
    NameModel(
      idNumber,
      randomFirstNameList.firstOrNull { it.idNumber == idNumber }?.firstName ?: "",
      randomLastNameList.firstOrNull { it.idNumber == idNumber }?.lastName ?: ""
    )
  }

输出(包括一个姓氏输入,没有相应的名字输入):

NameModel(idNumber=5631ab, firstName=Bob, lastName=Johnson)
NameModel(idNumber=ca790a, firstName=George, lastName=Takai)
NameModel(idNumber=j8f1sa, firstName=Alice, lastName=Smith)
NameModel(idNumber=999999, firstName=, lastName=NoFirstName)

附加说明:

如果两个列表非常大,则重复的 firstornull 调用可能会增加时间消耗。在这种情况下,为第一个和姓氏创建查找图是很有意义的:

val firstNameMap = randomFirstNameList.associate { it.idNumber to it.firstName }
val lastNameMap = randomLastNameList.associate { it.idNumber to it.lastName }

val map: List<NameModel> = randomFirstNameList.map { it.idNumber }
  .plus(randomLastNameList.map { it.idNumber })
  .distinct()
  .map { idNumber ->
    NameModel(
      idNumber,
      firstNameMap.getOrElse(idNumber) { "" },
      lastNameMap.getOrElse(idNumber) { "" }
    )
  }

This would work including the cases mentioned in @Sweeper's (thanks!) comment below the question:

val map: Map<FirstNameModel, LastNameModel> = randomFirstNameList.map { it.idNumber }
  .plus(randomLastNameList.map { it.idNumber })
  .distinct()
  .associate { idNumber ->
    (randomFirstNameList.firstOrNull { it.idNumber == idNumber } ?: FirstNameModel(idNumber, "")) to
    (randomLastNameList.firstOrNull { it.idNumber == idNumber } ?: LastNameModel(idNumber, ""))
  }

But it probably would make sense to introduce a data class to hold the result:

data class NameModel(val idNumber: String, val firstName: String, val lastName: String)

val map: List<NameModel> = randomFirstNameList.map { it.idNumber }
  .plus(randomLastNameList.map { it.idNumber })
  .distinct()
  .map { idNumber ->
    NameModel(
      idNumber,
      randomFirstNameList.firstOrNull { it.idNumber == idNumber }?.firstName ?: "",
      randomLastNameList.firstOrNull { it.idNumber == idNumber }?.lastName ?: ""
    )
  }

Output (including one last name entry without corresponding first name entry):

NameModel(idNumber=5631ab, firstName=Bob, lastName=Johnson)
NameModel(idNumber=ca790a, firstName=George, lastName=Takai)
NameModel(idNumber=j8f1sa, firstName=Alice, lastName=Smith)
NameModel(idNumber=999999, firstName=, lastName=NoFirstName)

Additional remark:

If the two lists are very large, the repeated firstOrNull calls could increase time consumption. In such a case it would make sense to create lookup maps for first and last names:

val firstNameMap = randomFirstNameList.associate { it.idNumber to it.firstName }
val lastNameMap = randomLastNameList.associate { it.idNumber to it.lastName }

val map: List<NameModel> = randomFirstNameList.map { it.idNumber }
  .plus(randomLastNameList.map { it.idNumber })
  .distinct()
  .map { idNumber ->
    NameModel(
      idNumber,
      firstNameMap.getOrElse(idNumber) { "" },
      lastNameMap.getOrElse(idNumber) { "" }
    )
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文