对列表中的数字的子集求和

时间:2017-10-20 15:58:51

标签: kotlin

Kotlin是否有办法在过滤的数字列表上执行sum()操作,而不先实际过滤掉这些元素?

我正在寻找类似的东西:

val nums = listOf<Long>(-2, -1, 1, 2, 3, 4)
val sum = nums.sum(it > 0)

2 个答案:

答案 0 :(得分:12)

您可以使用Iterable<T>.sumBy

/**
 * Returns the sum of all values produced by [selector] function applied to each element in the collection.
 */
public inline fun <T> Iterable<T>.sumBy(selector: (T) -> Int): Int {
    var sum: Int = 0
    for (element in this) {
        sum += selector(element)
    }
    return sum
}

您可以将函数传递给函数,函数将负值转换为0.因此,它会将列表中所有大于0的值相加,因为添加0不会对结果产生影响。

val nums = listOf<Long>(-2, -1, 1, 2, 3, 4)
val sum = nums.sumBy { if (it > 0) it.toInt() else 0 }
println(sum)    //10

如果您需要Long值,则必须为Long撰写Iterable<T>.sumByDouble的扩展程序。

inline fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long {
    var sum: Long = 0
    for (element in this) {
        sum += selector(element)
    }
    return sum
}

然后,toInt()转换可以被取消。

 nums.sumByLong { if (it > 0) it else 0 }

根据@Ruckus T-Boom的建议,if (it > 0) it else 0可以使用Long.coerceAtLeast()进行简化,nums.sumByLong { it.coerceAtLeast(0) } 返回值本身或给定的最小值:

if (conta1) and (15) = 15 then
    conta = conta - 6
end if

答案 1 :(得分:-2)

data class Product(val name: String, val quantity: Int) {
}

fun main(args: Array<String>) {

    val productList = listOf(
            Product("A", 100),
            Product("B", 200),
            Product("C", 300)
    )

    val totalPriceInList1: Int = productList.map { it.quantity }.sum()
    println("sum(): " + totalPriceInList1)

    val totalPriceInList2: Int = productList.sumBy { it.quantity }
    println("sumBy(): " + totalPriceInList2)
} 

这是我们代码的结果

sum(): 600
sumBy(): 600