【问题标题】:Kotlin declare nested arrayKotlin 声明嵌套数组
【发布时间】:2019-03-27 10:03:16
【问题描述】:

如何在 Kotlin 中声明嵌套列表? 我正在寻找以下形式的东西:

var nestedList:List = [1,[2,[3,null,4]],[null],5]

以便我以后可以将其展平(结果应该是 nestedList = [1, 2, 3, 4, 5])。

【问题讨论】:

  • 您希望这个结构具有什么数据类型? Kotlin 是一种静态类型语言,因此您可以拥有一个数组(或列表),其中每个元素也是一个数组(或列表),或者一个数组(或列表),其中每个元素都是一个值。
  • so 数组还是列表?:)
  • 考虑到我要解决的问题,我需要一个数组,其中每个元素也是一个数组。
  • 实际上在这个特定的例子中 Int 和 Array 类型是混合的。单个数组包含 1 和另一个数组:[1,[2,[3,null,4]],...]

标签: list arraylist kotlin nested declare


【解决方案1】:

如果你有嵌套数组结构(例如val array: Array<Array<out Int?>> = arrayOf(arrayOf(1), arrayOf(2), arrayOf(3, null, 4))),你可以使用flatten扩展方法:

println(array.flatten().filterNotNull())

【讨论】:

  • 这是我一直在寻找的,但有没有办法让我不必硬编码层数(在你的例子中是 2)?
  • 请男人不要在家里和工作中尝试。 inline fun <reified T> flatArray(array: Array<*>): Array<T> { var temp: Array<*> = arrayOf(*array) while (!temp.isEmpty() && temp[0] is Array<*>) { temp = flatLevel(temp) } val result: Array<T?> = arrayOfNulls(temp.size) for ((index, value) in temp.withIndex()) { result[index] = value as T } return result.asSequence().filterNot { it.isNull() }.toList().toTypedArray() as Array<T> }
  • fun flatLevel(array: Array<*>): Array<*> { if (!array.isEmpty()) { val result = mutableListOf<Any?>() for (innerArray in array) { val castedArray = innerArray as Array<*> for (innerItem in castedArray) { result.add(innerItem) } } return result.toTypedArray() } return array }
  • 我这样做是因为它具有挑战性。最好找到另一个不会导致此代码的解决方案。最好的办法是禁止变量深度并使用类型安全代码
【解决方案2】:

所有常见的集合都无法保持可变层数,因此使用它们您只能制作像 Andrey Ilyunin 所写的东西 - val array: Array<Array<out Int?>>

但我编写了类结构来帮助您实现目标。它不是另一个集合,你不能像它一样使用它,但它可以制作你想要的任何层数。它是完全通用的,所以你不仅可以把Int放在那里。

首先,我们从NestedArrayItem类开始,它表示单个项目或一个嵌套数组:

class NestedArrayItem<T> {
    private val array: ArrayList<NestedArrayItem<T>>?
    private val singleItem: T?
    constructor(array: ArrayList<NestedArrayItem<T>>) {
        this.array = array
        singleItem = null
    }
    constructor(singleItem: T?) {
        this.singleItem = singleItem
        array = null
    }
    fun asSequence(): Sequence<T?> =
        array?.asSequence()?.flatMap { it.asSequence() } ?:
            sequenceOf(singleItem)
    override fun toString() =
        array?.joinToString(prefix = "[", postfix = "]") ?:
            singleItem?.toString() ?: "null"
}

然后是 NestedArray 类,就像所有层的顶级容器:

class NestedArray<T> {
    private val array: ArrayList<NestedArrayItem<T>> = arrayListOf()

    fun add(value: T?) {
        array.add(NestedArrayItem(value))
    }

    fun addNested(nestedArray: NestedArray<T>) {
        array.add(NestedArrayItem(nestedArray.array))
    }

    fun flatten(): ArrayList<T?> = array.asSequence()
        .flatMap { it.asSequence() }
        .toCollection(arrayListOf())

    override fun toString() = array.joinToString(prefix = "[", postfix = "]")
}

为了更容易编写值,我还为此编写了构建器类:

class NestedArrayBuilder<T> private constructor(private val result: NestedArray<T>){
    constructor(fillNestedBuilder: NestedArrayBuilder<T>.() -> Unit) : this(NestedArray()) {
        NestedArrayBuilder(result).apply(fillNestedBuilder)
    }
    fun add(value: T?): NestedArrayBuilder<T> {
        result.add(value)
        return this
    }
    fun addArray(fillNestedBuilder: NestedArrayBuilder<T>.() -> Unit): NestedArrayBuilder<T> {
        val nestedResult = NestedArray<T>()
        val nestedArray = NestedArrayBuilder(nestedResult).apply(fillNestedBuilder)
            .build()
        result.addNested(nestedArray)
        return this
    }

    fun build() = result
}

就是这样!你可以使用它。我在这里举个例子如何使用它:

val array = NestedArrayBuilder<Int> {
    add(1)
    addArray {
        add(2)
        addArray {
            add(3)
            add(null)
            add(4)
        }
    }
    addArray {
        add(null)
    }
    add(5)
}.build()
assertEquals("[1, [2, [3, null, 4]], [null], 5]", array.toString())
assertEquals(arrayListOf(1, 2, 3, null, 4, null, 5), array.flatten())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 2019-10-28
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 2015-03-14
    相关资源
    最近更新 更多