Kotlin 函数式编程保留 List 中前一个对象的引用

Kotlin functional programming keep reference of previous object in List

我有一个 Person 对象的列表,这些对象按照它们在列表中出现的顺序与配偶关系相互关联。

enum class Gender {
    MAN, WOMAN
}
data class Person(val name: String, val age: Int, val gender: Gender)

在列表中,每个性别为 MAN 的人都是以下性别为 WOMAN 的人的配偶(反之亦然),并且列表中的每个条目后面都是交替的性别,MAN 性别是第一个。

理想情况下,该列表应该像 [MAN, WOMAN, MAN, WOMAN, MAN, WOMAN](显然它将是一个 Person 对象列表,为简单起见,我在此处放置了一个 Gender 列表),但它也可以像 [WOMAN, MAN, WOMAN, MAN, WOMAN, MAN]。在后一种情况下,第一个出现的女人是最后一个出现的男人的配偶。

如何使用函数式编程在 kotlin 中处理第二种情况。 我目前的方法包括检查第一个人是否有性别女性,然后我删除列表中的第一个和最后一个对象,然后将它们添加到最后,但这不是一个完整的函数式编程解决方案。

有人可以指导我吗?

谢谢

全功能方法是什么意思?
与您提到的类似,您可以通过这样的简单语句来修复顺序:

val correctList = if(list.first().gender == MAN) list else list.drop(1) + list.first()

如果你想要一个更通用的方法,你可以这样做:

    // separate the people into a list of gender=MAN and a list of everyone else
    // the result is a Pair, so I'm destructuring that into two variables
    val (men, women) = people.partition { it.gender == MAN }
    // use zip to take a person from each list and combine them into a list of pairs
    men.zip(women)
    // use flatMap to turn each pair into a list of two people
    // just using map would create a list of lists, flatMap flattens that into
    // a single list of people, alternating gender=MAN, gender=WOMAN 
       .flatMap { it.toList() }

这样,原始列表的排序方式无关紧要,它可以从任何元素开始,并且您可以将不同的类型完全混合 - BABBAABA 仍然会显示为 ABABABAB.所以这是合并混合数据流的通用方法 - partition 将它们分成几组,而 zip 允许您从每个组中取出一个元素并对它们进行处理。

在这里,我只是让 zip 创建 Pair,然后 flatMap 将它们变回有序列表(如果这是您想要的)。你也可以在每一对上做一个 forEach (比如你想在每个 Person 上设置一个值到 link 它们彼此),或者 zip 可以采取还有一个转换函数。

当其中一个列表用完时 zip 也会终止(例如,对于 AAABB 你会得到两对)所以这适用于生成完整的元素对 -如果你还需要在没有“伙伴”的情况下处理元素,你需要做更多的工作