【问题标题】:Initializing an Array using lambda with conditions in Kotlin在 Kotlin 中使用带有条件的 lambda 初始化数组
【发布时间】:2020-01-30 11:52:00
【问题描述】:

信息

我有一个 Item 类文件如下:

class Item(var color:String, var numValue:Int, var drawableID:Int){
    init {
        color = this.color
        numValue = this.numValue
        drawableID = this.drawableID
    }
}

在主代码中,我创建了一个默认属性包含 104 个对象的数组:

var myItemClassArray = Array(104) { Item("", -99, -99) }

我的可绘制文件夹中还有图片,它们的 ID 位于 drawablesIDs:Array<Int> 数组中,它包含 53 个元素。

问题

我想分配我的 Item 属性,如下图所示:https://i.stack.imgur.com/wFVsn.png 我可以使用下面给出的代码来解决类似的问题(有 106 个对象和 53 个可绘制对象):

        for (i in 0 until 106) {
            if (i < 13) {
                myItemClassList[i+2].color = "kirmizi"
                myItemClassList[i+2].numValue = i+1
                myItemClassList[i+2].drawableID = drawablesIDs[i+1]
            } else if (i in 13..25) {
                myItemClassList[i+2].color = "siyah"
                myItemClassList[i+2].numValue = (i+1)-13
                myItemClassList[i+2].drawableID = drawablesIDs[i+1]
            } else if (i in 26..38) {
                myItemClassList[i+2].color = "yesil"
                myItemClassList[i+2].numValue = (i+1)-26
                myItemClassList[i+2].drawableID = drawablesIDs[i+1]
            } else if (i in 39..51) {
                myItemClassList[i+2].color = "mavi"
                myItemClassList[i+2].numValue = (i+1)-39
                myItemClassList[i+2].drawableID = drawablesIDs[i+1]
            } else if (i in 52..64) {
                myItemClassList[i+2].color = "kirmizi"
                myItemClassList[i+2].numValue = (i+1)-52
                myItemClassList[i+2].drawableID = drawablesIDs[(i+1)-52]
            } else if (i in 65..77) {
                myItemClassList[i+2].color = "siyah"
                myItemClassList[i+2].numValue = (i+1)-65
                myItemClassList[i+2].drawableID = drawablesIDs[i+1-65+13]
            } else if (i in 78..90) {
                myItemClassList[i+2].color = "yesil"
                myItemClassList[i+2].numValue = (i+1)-78
                myItemClassList[i+2].drawableID = drawablesIDs[i+1-78+26]
            } else if (i in 91..103) {
                myItemClassList[i+2].color = "mavi"
                myItemClassList[i+2].numValue = (i+1)-91
                myItemClassList[i+2].drawableID = drawablesIDs[i+1-91+39]
            } else {
                myItemClassList[0].color = "sahte"
                myItemClassList[0].drawableID = drawablesIDs[0]
                myItemClassList[1].color = "sahte"
                myItemClassList[1].drawableID = drawablesIDs[0]
            }
        }

有没有更简洁的方法来做到这一点?

可以使用 lambda 表达式来创建数组。例如:

val test = Array(28){i-> examples[i]}

这适用于一个“i”参数。但如果我想尝试这样的事情:

val test = Array(28){if(i<13)-> examples[i]}

它给了我一个错误,因为它的语法是错误的。

更简单的问题

假设我们有一个从 0 到 28 的数组,如下所示:

val testNumbers= Array(28){i->i}

现在我想使用 lambda 创建一个包含从 0 到 10 的数字的数组。 我该怎么做:

val player6 = Array(10){(it<10) -> testNumbers[it]} // gives an syntax error

【问题讨论】:

  • 对于您的简单问题,简单回答。使用 .filter { 它
  • 您可以使用when 语句,但它不会大大缩短此代码...

标签: android arrays kotlin lambda initialization


【解决方案1】:

根据我从你的照片中收集到的信息,我做了以下三个假设:

  • numValue 以 13 项为一组进行分组
  • 每组按顺序收到一种颜色:kirmizi -> siyah -> yesil -> mavi,然后再次循环
  • 可绘制 ID 每 52 个项目循环一次

基于此,我想出了以下解决方案:

data class Item(var color: String = "", var numValue: Int = -99, var drawableId: Int = -99)

fun main() {
    val colors = listOf("kirmizi", "siyah", "yesil", "mavi")
    val drawableIDs = (0..52).toList()  // This is just a stub. in your case it will be your drawable lists

    val edgeCase = arrayListOf(Item("sahte", drawableId = drawableIDs[0]), Item("sahte", drawableId = drawableIDs[0]))

    val pattern = (0 until 104)
        .map { index ->  Pair(index, index / 13) }
        .map { (index, group) -> 
            Item(
                color = colors[group % 4], 
                numValue = index+1, 
                drawableId = drawableIDs[(index % 52) + 1]
            ) 
        }

    val total = pattern + edgeCase 
    total.forEach { println(it) }
}

您可以在kotlin playground 上玩弄它。

有更清洁的方法吗?

据我所知,您只想初始化一个包含 28 个空格的连续数组的前 13 个值,其余的保留默认值或 null。

您的代码不起作用的原因是Array 初始化程序希望您返回一个对象。 if 块本身不是 kotlin 中的表达式,因此它不会计算为值,因此您需要提供一个 else 分支才能使其工作。

val examples = Array(28) { if (i < 13) examples[i] else defaultExample }

这在Kotlin documentation for control flow:

中有说明

如果您将 if 用作表达式而不是语句(例如,返回其值或将其分配给变量),则表达式必须具有 else 分支。 p>


更简单的问题

在这种情况下,您可以只使用take:

// If you don't want to modify it
val player6 = testNumbers.take(10)
                   .toTypedArray()  // Since take returns a List, you need to turn it back into an array

// If you want to modify the items
val player6 = testNumbers.take(10)
                    .map { value -> modifyNumber(value) }
                    .toTypedArray()

提示:在 kotlin 中,如果您使用 valvar 声明构造函数参数,它们已经是您的类中的属性,您无需在 init 块中手动初始化.

/*
 * You don't need to do this:
 * class Item(var color: String, var numValue: Int, var drawableId: Int) {
 *    init {
 *      this.color = color
 *      this.numValue = numValue
 *      this.drawableId = drawableId
 *    }
 * }
 */

// Kotlin already does it for you
class Item(var color: String, var numValue: Int, var drawableId: Int)

fun main() {
    val myitem = Item("blue", 20, 100)

    println(myitem.color)
    println(myitem.numValue)
    println(myitem.drawableId)
}

【讨论】:

    【解决方案2】:

    这是一个可能的解决方案:

    fun getColor(i: Int) = when (i) {
      in 0..1 -> "sahte"
      in 2..13, in 52..64 -> "kirmizi"
      in 65..77, in 13..25 -> "siyah"
      in 26..38, in 78..90 -> "yesil"
      in 39..51, in 91..103 -> "mavi"
      else -> ""
    }
    
    fun getNumValue(i: Int) = when (i) {
      in 0..1 -> -99
      in 2..13 -> i - 1
      in 13..25 -> (i - 1) - 13
      in 26..38 -> (i - 1) - 26
      in 39..51 -> (i - 1) - 39
      in 52..64 -> (i - 1) - 52
      in 65..77 -> (i - 1) - 65
      in 78..90 -> (i - 1) - 78
      in 91..103 -> (i - 1) - 91
      else -> -99
    }
    
    fun getDrawableID(i: Int) = when (i) {
      in 0..1 -> drawablesIDs[0]
      in 2..13, in 13..25, in 26..38, in 39..51 -> drawablesIDs[i - 1]
      in 52..64 -> drawablesIDs[(i - 1) - 52]
      in 65..77 -> drawablesIDs[i - 1 - 65 + 13]
      in 78..90 -> drawablesIDs[i - 1 - 78 + 26]
      in 91..103 -> drawablesIDs[i - 1 - 91 + 39]
      else -> -99
    }
    
    val myItemClassArray = Array(104) {
      Item(getColor(it), getNumValue(it), getDrawableID(it))
    }
    

    可能在不同的范围内有一些错误。

    主要优点是:

    • 每个映射都可以独立测试
    • 没有可变性

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-29
      • 2020-02-04
      • 1970-01-01
      • 1970-01-01
      • 2019-08-21
      • 2015-09-30
      相关资源
      最近更新 更多