为什么Kotlin数组不返回计数

时间:2019-03-26 14:24:59

标签: android arraylist kotlin

我有一个模型对象,该对象具有一个数组列表映射。

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"]

现在我要计算上面提取的数组中有多少个元素。为此,我尝试从上面创建另一个元素数组,然后执行count和size函数。但是,这没有用。

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

3 个答案:

答案 0 :(得分:3)

根据您的代码,我将假定您已将其完全解析为Map<K, V>。如果有,原因非常容易找到:您已将Array(/ List)添加到Array中。这意味着您的尝试会给您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()

我不推荐这种方法 -在您的情况下,这是过分的做法,并且会降低性能。我之所以提及它,是因为它是 a 解决方案。

正如Boken已经提到的那样,您根本不需要将其包装在Array中。如果将其存储为Map,则已经有一个List或Array,并且可以使用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对象获取一个数组/列表,并在其上运行长度。我将向您展示此部分的代码,但是在不知道您使用什么(内置,Jackson,Gson等)的情况下,我没有足够的细节来显示任何代码。尽管如此,这个想法仍然是直接从JSONObject获取大小,或者获取一个可以在其上运行大小的数组。


进一步阅读

答案 1 :(得分:1)

使用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
}

答案 2 :(得分:0)

问题:

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),因为这是一个约定。