【问题标题】:Kotlin - Append element in a list from a map - Expecting List<Object>, Found List<Kotlin.Unit>Kotlin - 在地图的列表中附加元素 - 期望 List<Object>, Found List<Kotlin.Unit>
【发布时间】:2021-10-13 22:18:04
【问题描述】:

我有一个包含键和翻译的消息对象列表。

val messages = mutableListOf<Message>()

从此消息列表中,我想从中获取翻译。

在简单地映射到 Translation 对象之前,我正在检查我的 Message 对象的特定属性,然后循环遍历一个附加列表以将新翻译附加到我的列表中。

消息由 4 个元素组成,我希望在迭代 messages.list 时总共有 6 个元素

得到:

  • 元素[0](解锁=假):翻译(message.key)
  • 元素[1](解锁=真):kotlin.Unit
  • 元素[2](解锁=真):kotlin.Unit
  • 元素[3](解锁=false):翻译(message.key)

预期:

  • 元素[0](解锁=假):翻译(message.key)
  • 元素[1](解锁=真):翻译(“解锁”)
  • 元素[2](解锁=真):翻译(“解锁”)
  • 元素[3](解锁=真):翻译(“解锁”)
  • 元素[4](解锁=真):翻译(“解锁”)
  • 元素[5](解锁=false):翻译(message.key)

代码:

val translationList = messages.map { message ->
            if (message.unlock == "true") {
                message.list.forEachIndexed { index, item ->
                    Translation("unlock")
                }
            }
            else {
                    Translation(message.key)
            }

我可以清楚地看到迭代已正确完成,但附加失败。

如何遍历地图中的列表,将 Translation 对象附加到同一列表中并避免使用 Kotlin.Unit 类型?

Edit1:添加消息和翻译类

data class Message(@JacksonXmlProperty(localName = "unlock", isAttribute = true)
                   val unlock: String? = null,
                   @JacksonXmlProperty(localName = "key")
                   val key: String? = null,
                   @JacksonXmlProperty(localName = "list")
                   val list: MutableList<String>? = null,
                   @JacksonXmlElementWrapper(useWrapping = true)
                   @JacksonXmlProperty(localName = "translation")
                   val translation: Translation? = null)

data class Translation(@JacksonXmlProperty(localName = "type", isAttribute = true)
                       val type: String? = null,
                       @JacksonXmlProperty(localName = "innerText")
                       @JacksonXmlText
                       val text: String? = null)

【问题讨论】:

  • @Sweeper 刚刚添加了一些说明。我实际上是在解析一个自定义 XML 文件,其中有 Message 和 Translation 属性。
  • 刚刚修复了Message类:)

标签: list dictionary kotlin foreach iterator


【解决方案1】:

由于您想将一件事映射到多件事,您应该使用flatMap。在 flatMap 的 lambda 中,您可以返回一个 Iterable,其中包含您想要将每个元素映射到的事物。

val translationList = messages.flatMap { message ->
    // you might want to use a Bool for message.unlock instead :)
    if (message.unlock == "true") {
        // we transform each element of message.list into a translation
        // forEach gives you Unit, map gives you the transformed list
        message.list.map { Translation("unlock") }
    }
    else {
        listOf(Translation(message.key))
    }
}

【讨论】:

  • 太棒了,就是这样!只是没有使用正确的工具。感谢这个快速的解决方案!
【解决方案2】:

您的 messages.map 调用将每条消息映射到内部 lambda 调用的结果:

        message ->
            if (message.unlock == "true") {
                message.list.forEachIndexed { index, item ->
                    Translation("unlock")
                }
            }
            else {
                    Translation(message.key)
            }

else 部分很简单——只需将其映射到新的 Translation 对象。但是在 if 部分它很棘手 - lambda 的返回值是最后一行,即 message.list.forEachIndexed,它返回 Unit - forEachIndexed 中发生的所有内容都不会存储在任何地方,您只需创建和实例化并且什么都不做它

【讨论】:

  • 你会建议使用return@forEachIndexed 吗?
  • 我建议使用flatMap,就像@Sweeper 建议的那样
猜你喜欢
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
相关资源
最近更新 更多