Kotlin优雅地将List<Triple<String, String, String>>变异为Triple<List<String>, List<String>, List<String>>的方法

4
我将尽可能简明清晰地将一个类型为List<Triple<String, String, String>>的列表转换为Triple<List<String>, List<String>, List<String>>三元组。请考虑以下示例,如果执行转换的方法名为turnOver,则期望输出:
val matches = listOf(
  Triple("a", "1", "foo"),
  Triple("b", "2", "bar"),
  Triple("c", "3", "baz"),
  Triple("d", "4", "qux")
)
val expected = Triple(
  listOf("a", "b", "c", "d"),
  listOf("1", "2", "3", "4"),
  listOf("foo", "bar", "baz", "qux")
)
matches.turnOver() == expected // true

如何编写简洁、清晰、且可能具有功能性的 turnOver 函数?

可以使用 Arrow-Kt,我已将其作为项目依赖项。


这个操作通常被称为“解压缩”。 - Joseph Sible-Reinstate Monica
是的,它类似于解压缩,但据我所知,至少在 Kotlin 中,(un)zip 适用于 List<Pair>/Pair<List>。我想要一个通用版本,可能适用于 n 元组。@alexey-romanov 下面提出了 Arrow-Kt 中的 Traverse,我要看看它是否适合。 - Danilo Pianini
2个回答

8
fun turnOver(matches: List<Triple<String, String, String>>) = Triple(
   matches.map { it.first },
   matches.map { it.second },
   matches.map { it.third },
)

我想一个明显的解决方案是使用“我估计”。

3
不错,但在我看来,我想要一个更通用的解决方案,其中代码不会随着元组大小的增加而增长。我相信在函数式编程中会有一种惯用法来实现这种解包。 - Danilo Pianini
1
@DaniloPianini,既然您提到了Arrow-Kt,那么这实际上是Traverse(https://arrow-kt.io/docs/0.10/apidocs/arrow-core-data/arrow.typeclasses/-traverse/)的一个应用。但不是使用标准实例,因此如果您想使用它,仍需要为每个元组大小编写更通用的版本。 - Alexey Romanov
这个解决方案对matches执行n次迭代,而对于成对的.unzip()函数只执行一次,就像手动迭代并将元素添加到MutableList一样。 - undefined

-2
据我所知,在kotlin stdlib中,没有办法从一个可迭代对象、数组或序列中创建一个Pair或Triple。我认为这是有意为之的。因此,我想上面的那个解决方案是最清晰明了的。

这是作为答案发布的,但它并没有试图回答问题。它可能应该是一个编辑、评论、另一个问题或完全删除。(但我的标记被拒绝了。) - aneroid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接