Почему массив Kotlin не возвращает счет - PullRequest
0 голосов
/ 26 марта 2019

У меня есть объект модели, у которого есть Карта списков массивов.

data class ResponseModel(
    val schedule: Map<String, ArrayList<String>>,
    val target_temp: String

)

Это успешно анализирует данные, поступающие из данных примера API, как показано ниже.

{
    "limit": "10",
    "schedule": {
        "0": ["0", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"],
        "1": ["1", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"],
        "2": ["2", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"],
        "3": ["3", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"],
        "4": ["4", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"],
        "5": ["5", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"],
        "6": ["6", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"]
    },
    "target_temp": "32.18"
}

Я могу получить доступ к отдельным значениям массива согласно ключу в моем расписании, с помощьюследующий код.

holder?.view?.start?.text = responseModel.schedule.get("0").toString()

Это дает мне желаемые результаты

["0", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"]

Теперь я хочу посчитать, сколько элементов находится в извлеченном выше массиве.Чтобы добиться этого, я попытался создать еще один массив элементов сверху, а затем выполнил функции подсчета и размера.Однако это не сработало.

arrayOf(responseModel.schedule.get("0")).count()

Ответы [ 3 ]

3 голосов
/ 26 марта 2019

Исходя из вашего кода, я предполагаю, что вы полностью проанализировали его в Map<K, V>.Если у вас есть, причина очень легко найти: вы добавили массив (/ список) в массив.Это означает, что ваша попытка дает вам Array<Array<String>> или Array<List<String>>.

Если вы снова посмотрите на свой код, вы добавите только один элемент или один массив в массив.Если вы проанализируете его обратно в JSON, он будет выглядеть следующим образом:

[
    [
        "0", "3.00", ...
    ]
]

Основываясь на примере JSON, приведем пример псевдокодирования вашего текущего кода:

[
    [
        "0", "3.00", ...
    ]
].size()

Что естественновозвращает 1: у вас есть только один элемент в родительском.

Если вы хотите, чтобы он работал точно так, как у вас сейчас, вам нужно использовать оператор распространения (*).arrayOf занимает vararg, и вы должны распространить исходный массив в vararg, чтобы не пропустить массив.Это дает вам Array<String> (или, возможно, Array<Any> в зависимости от карты):

arrayOf(*responseModel.schedule.get("0")).count()

Я не рекомендую такой подход - это переборв вашем случае и снизит производительность.Я упоминаю об этом, потому что это решение .

Как уже упоминал Бокен, вам вообще не нужно оборачивать его в массив.Если вы храните его как карту, у вас уже есть список или массив, и вы можете получить к нему невероятный доступ просто с помощью responseModel.schedule.get("0").size.

Если вы сохраните его как Any (что, я полагаю, у вас есть), выПридется добавить дополнительный шаг:

val cache = responseModel.schedule.get("0"); // Any, in reality Array<String>/Array<Any>/List<Any>/List<String>
if (cache is Array) println(cache.size)
else if(cache is List) println(cache.size)

Приведение здесь заключается в том, чтобы получить автоматический вывод типа - если у вас есть Any, компилятор не знает, имеет ли оно поле sizeи поэтому будет выбрасывать исключение.

Конечно, вы можете разыграть его напрямую, но это не очень хорошая идея, если вы когда-нибудь получите другой ввод (намеренно или случайно)


Если, однако,вы на самом деле не храните его в форме карты, что усложняет ситуацию.Чтобы не отставать от первой части, у вас будет Array<JSONObject>, и у вас будет только один JSONObject в массиве.

В отличие от предыдущей части, вы не можете использовать оператор распространения и получить его прямо в Array (который, опять же, я не рекомендую вам использовать, если вам не нужно)

Если вы сохраняете JSONObject для любой используемой вами системы, он может иметь поле / функцию размера / длины, которые вы можете использовать, и это не так сложно.В противном случае вам нужно получить массив / список из объекта JSON и выполнить для него длину.Я хотел бы показать вам код для этой части, но, не зная, что вы используете (встроенный, Джексон, Gson и т. Д.), У меня недостаточно подробностей, чтобы показать какой-либо код.Тем не менее, идея по-прежнему заключается в том, чтобы получить размер непосредственно из JSONObject или получить массив, для которого вместо этого можно запустить размер.


Дальнейшее чтение

1 голос
/ 26 марта 2019

Оборачивая карту с помощью arrayOf(...) вы создаете новую структуру - массив, содержащий списки.

Вы должны изменить его с:

arrayOf(responseModel.schedule.get("0")).count()

на:

responseModel.schedule["0"]?.size
// or
responseModel.schedule["0"]?.count()

Полный пример:

fun main() {
    val schedule = mapOf(
        "0" to listOf("0", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"),
        "1" to listOf("1", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"),
        "2" to listOf("2", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"),
        "3" to listOf("3", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"),
        "4" to listOf("4", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"),
        "5" to listOf("5", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59"),
        "6" to listOf("6", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59")
    )

    println(schedule["0"])
    // output:  [0, 3.00, 7.59, 9.00, 12.59, 14.00, 22.59]

    println(schedule["0"].count())
    // output:  7
    // because you have list with 7 elements

    println(arrayOf(schedule["0"]).count())
    // output:  1
    // because you have array with 1 element - you have array of lists
}
0 голосов
/ 26 марта 2019

Проблема:

arrayOf(responseModel.schedule.get("0")).count()

создаст список со списком в качестве единственного элемента.Вот почему count вернет 1.

Решение:

Если после анализа ваши данные выглядят так:

val responseModel = ResponseModel(
        schedule = mapOf(
                "0" to arrayListOf("3.00", "7.59", "9.00", "12.59", "14.00", "22.59"),
                "1" to arrayListOf("1", "3.00", "7.59", "9.00", "12.59", "14.00", "22.59")
                // ...
        ),
        target_temp = "32.18"
)

каждыйЭлемент расписания будет ArrayList, для которого вы можете определить размер следующим образом:

val numElements = responseModel.schedule["0"]?.size

Примечание:

  • Вы можете использовать нотацию оператора get [] вместо вызова его как функции:

    val firstLinesValues = responseModel.schedule["0"]
    
  • Пожалуйста, используйте верблюжий регистр для имен переменных (target_temp -> targetTemp), так как это соглашение.

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