Инициализация массива с использованием лямбды с условиями в Kotlin - PullRequest
0 голосов
/ 30 января 2020

Информация

У меня есть файл класса 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) }

Также у меня есть рисунки в моей папке для рисования, и их идентификаторы в массиве drawablesIDs:Array<Int>, и он содержит 53 элемента.

Проблема

Я хочу назначить свой элемент атрибуты, как на этом рисунке: 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]
            }
        }

Есть ли более чистый способ сделать это?

Можно использовать лямбда-выражение для создания массива. Например:

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}

Теперь я хочу создать массив, который будет содержать числа от 0 до 10, используя лямбду. Как мне это сделать:

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

Ответы [ 2 ]

0 голосов
/ 30 января 2020

Из того, что я мог бы извлечь из вашей картинки, я сделал три предположения:

  • Значение numValue сгруппировано в группы по 13 элементов
  • Каждая группа получает цвет в порядок: kirmizi -> siyah -> yesil -> mavi, затем он циклически повторяется
  • Выделяемые идентификаторы циклически повторяются каждые 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 детской площадке .

Есть ли более чистый способ сделать это ?

Исходя из того, что я понял, вы хотите инициализировать только первые 13 значений непрерывного массива с 28 пробелами, оставляя остальные либо с их значениями по умолчанию, либо с нулем.

Причина, по которой ваш код не работает, заключается в том, что инициализатор Array ожидает, что вы вернете объект. сам по себе блок if не является выражением в kotlin, поэтому он не оценивается как значение, поэтому для его работы необходимо предоставить ветвь else.

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

Это указано в документации Kotlin для потока управления :

Если вы используете if как выражение, а не как оператор (например, возвращая его значение или присвоение его переменной), выражение должно иметь ветвь else.


Более простой вопрос

В этом случае вы можете просто использовать 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, если вы объявите свой параметр конструктора с val или var они уже являются атрибутами вашего класса, и вам не нужно инициализировать вручную в блоке 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)
}
0 голосов
/ 30 января 2020

Вот возможное решение:

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))
}

Возможно, есть ошибки в разных диапазонах.

Основные преимущества:

  • каждое отображение тестируется независимо
  • нет изменчивости
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...