Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sum a subset of of numbers in a list

Tags:

kotlin

Is there a way in Kotlin for doing the sum() operation on a filtered list of numbers, without actually filtering out the elements first?

I'm looking for something like this:

val nums = listOf<Long>(-2, -1, 1, 2, 3, 4)
val sum = nums.sum(it > 0)
like image 866
Nate Jenson Avatar asked Oct 20 '17 15:10

Nate Jenson


People also ask

What is sum of subset problem explain with example?

Statement: Given a set of positive integers, and a value sum, determine that the sum of the subset of a given set is equal to the given sum. Given an array of integers and a sum, the task is to have all subsets of given array with sum equal to the given sum. Subset {4, 5} has the sum equal to 9.

How do you find the subset of a list?

If a set has “n” elements, then the number of subset of the given set is 2n and the number of proper subsets of the given subset is given by 2n-1. Consider an example, If set A has the elements, A = {a, b}, then the proper subset of the given subset are { }, {a}, and {b}.


2 Answers

sumBy and sumByDouble are Deprecated from kotlin 1.5 . You can check those link.

Use sumOf to get sum on a List or Array

sumOf

Returns the sum of all values produced by selector function applied to each element in the collection or Array.

Example:

data class Order(
  val id : String,
  val price : Double
) 

val orderList = ......
val sum = orderList.sumOf { it.price }
like image 110
Abu Yousuf Avatar answered Jan 05 '23 22:01

Abu Yousuf


You can make use of 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
}

You can pass a function to it where the function transforms negative value to 0. So, it sums up all values in the list which is greater than 0 since adding 0 makes no effect to the result.

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

If you require a Long value back, you have to write an extension for Long just like 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
}

Then, the toInt() conversion can be taken away.

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

As suggested by @Ruckus T-Boom, if (it > 0) it else 0 can be simplified using Long.coerceAtLeast() which returns the value itself or the given minimum value:

nums.sumByLong { it.coerceAtLeast(0) }
like image 37
BakaWaii Avatar answered Jan 05 '23 23:01

BakaWaii