Is there a sumBy equivalent for multiplication? - kotlin

I have an array of classes with values. E.g.
class MyData(val value: Double)
class MyClass(val values: List<MyData>)
it's pretty easy to get the sum of all values in the array:
values.sumByDouble { it.value }
Is there an equivalent to multiply these values inside those classes?

You can create an extension function:
public inline fun <T> Iterable<T>.multiplyByDouble(selector: (T) -> Double): Double {
this.firstOrNull() ?: return 0.0
var result = 1.0
for (element in this) {
result *= selector(element)
}
return result
}
and use it:
listOf(2.0, 3.0).multiplyByDouble { it } // 6.0
listOf<Double>().multiplyByDouble { it } // 0.0

There is no dedicated function for that, but you can use reduce for that. But there is a problem. Since the element (in this case of type T with S as upper bound) has to be a subtype of the accumulator (in this case of type S),
inline fun <S, T : S> Iterable<T>.reduce(
operation: (acc: S, T) -> S
): S
which is not the case in your example, it would be a good idea to first map the MyData elements to the Double value:
val l = listOf(MyData(1.0), MyData(2.0), MyData(3.0))
.map { it.value }
.reduce { acc, ele -> acc * ele }
println(l) // 6.0
Alternatively, you could change your data model (like shown here) but that might not be a good idea just for the sake of multiplying all values, but it depends on your use-case.

Related

Is there a Kotlin equivalent for Groovy's findIndexValues?

Does Kotlin have something to filter a collection and return the matching indexes?
E.g. like Groovy's findIndexValues:
http://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/Iterable.html#findIndexValues(groovy.lang.Closure)
Something like:
fun <T> List<T>.findIndexValues(predicate: (T) -> Boolean): List<Int> {
var indexValues = mutableListOf<Int>()
this.forEachIndexed { index, it ->
if (predicate(it)) {
indexValues.add(index)
}
}
return indexValues
}
The simplest way I can think of to do this is to use mapIndexedNotNull:
fun <T> List<T>.findIndexValues(predicate: (T) -> Boolean): List<Int> =
mapIndexedNotNull { i, t -> i.takeIf { predicate(t) } }
I don't believe there's a function for this in the standard library.
There are basically 2 simple ways according to me.
//say there is a List x of Strings
val x = listOf<String>()
//I don't believe you are looking for this.
//string is the required String of x at index.
for ((index, string) in x.withIndex()) {
TODO()
}
//2nd method is using filterIndexed
/**
* Returns a list containing only elements matching the given predicate.
* #Params: predicate - function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element.
*/
x.filterIndexed { index, string ->
TODO()
}
I like #Sam's answer, but I find this implementation to be slightly more readable as it filters explicitly on predicate as opposed to implicitly via null:
fun <T> List<T>.findIndexValues(predicate: (T) -> Boolean): List<Int> =
withIndex().filter { (_, t) -> predicate(t) }.map { it.index }

How do I pass an anonymous function to map()?

I'm working through a little code challenge in Kotlin.
Write a function that nests the elements of a list one level deeper by repeating that
element inside a new list a given number of times.
Examples
(nest [:a :b :c] 2) ;=> ((:a :a) (:b :b) (:c :c))
(nest [] 10) ;=> ()
(nest [1 2 3 4] 1) ;=> ((1) (2) (3) (4))
(nest [1 2 3] 0) ;=> (()()())
I implemented nest like so:
fun <R> nest(list: List<R>, repeat: Int) =
list.map{
mem -> generateSequence(1) { it }
.map { mem }
.take(repeat)
.toList()
}
However, I'm wondering how I'd write the lambda as a separate anonymous function, which I'd pass to map, like...
val anonFunction = ???
list.map(anonFunction)
I'm not sure how this would work syntactically.
Curly braces is what starts a lambda function in Kotlin. The only thing you need to do to assign an arbitary lambda to a val, is to let Kotlin know what type it has.
This is probably the simplest way to do it. I am giving the compiler the type of the parameter, but letting type inference take care of the return type.
fun <R> nest(list: List<R>, repeat: Int): List<List<R>> {
val anonFunction = { mem: R ->
generateSequence(1) { it }
.map { mem }
.take(repeat)
.toList()
}
return list.map(anonFunction)
}
You could also do it by specifying the full function type of anonFunction by declaring it like this:
fun <R> nest(list: List<R>, repeat: Int): List<List<R>> {
val anonFunction: (R) -> List<R> = { mem ->
generateSequence(1) { it }
.map { mem }
.take(repeat)
.toList()
}
return list.map(anonFunction)
}
Side note:
A simpler implementation of your challenge could be this:
fun <R> nest(list: List<R>, repeat: Int) = list.map { elem ->
List(repeat) { elem }
}

How to recursively implement a deep flatten on Iterable?

Having seen flatten, I was looking for something that would be a deepFlatten, i.e., it would work with not only Iterable<Iterable<T>> (it's pretty much the same for Arrays, but let's focus on Iterable now for brevity), but also with Iterable<Iterable<Iterable<T>>>, Iterable<Iterable<Iterable<Iterable<T>>>> and so on...
Of course, the result would have to be List<T>, which the standard flatten() doesn't provide - it would return List<Iterable<T> (or a List with more nested Iterables).
I was trying to work with reified generics:
inline fun <reified E, T> Iterable<E>.deepFlatten(): List<T> = when(E::class) {
Iterable<*>::class -> (this as Iterable<Iterable<*>>).flatten().deepFlatten()
else -> flatten()
}
But this obviously is flooded with errors:
T seems pretty undeducible
You cannot have a ::class of an interface
You cannot recurse on an inline function
Are there any workarounds on the above problems? Or, even better, is there a cleaner approach to the problem?
To demonstrate an example for completeness, I'd like to be able to do:
fun main() {
val data: List<List<List<Int>>> = listOf(
listOf(listOf(1, 2, 3), listOf(5, 6), listOf(7)),
listOf(listOf(8, 9), listOf(10, 11, 12, 13))
)
print(data.deepFlatten()) // 1 2 3 4 5 6 7 8 9 10 11 12 13
}
The depth of nested Iterables (they need not be the same type - it's important that they are generically Iterable) can vary.
In Java, you might achieve the very same behavior using java-stream:
Using Collection<?>:
public static Stream<?> deepFlatMap(Object o) {
if (o instanceof Collection<?>) {
return ((Collection<?>) o).stream().flatMap(i -> deepFlatMap(i));
}
return Stream.of(o);
}
Using Iterable<?>:
public static Stream<?> deepFlatMap(Object o) {
if (o instanceof Iterable<?>) {
Spliterator<?> spliterator = ((Iterable<?>) o).spliterator();
return StreamSupport.stream(spliterator, false).flatMap(i -> deepFlatMap(i));
}
return Stream.of(o);
}
The usage is pretty straightforward: deepFlatMap(list).forEach(System.out::println);
As long as I don't know Kotlin, I hope this can at least help you with rewriting the idea.
Edit: As long as you want to specify the return target generic type, you should use another wrapper method (don't forget to change the name in the recursive method):
public static <T> Stream<T> deepFlatMap(Collection<?> collection) {
return (Stream<T>) internalDeepFlatMap(collection);
}
public static Stream<?> internalDeepFlatMap(Object o) {
if (o instanceof Collection<?>) {
return ((Collection<?>) o).stream().flatMap(i -> internalDeepFlatMap(i));
}
return Stream.of(o);
}
Usage with specifying the generic type explicitly:
MyClass.<Integer>deepFlatMap(list).map(i -> i + 1).forEach(System.out::println);
fun <T> Iterable<*>.deepFlatten(): List<T> {
val result = ArrayList<T>()
for (element in this) {
when (element) {
is Iterable<*> -> result.addAll(element.deepFlatten())
else -> result.add(element as T)
}
}
return result
}
...
println(data.deepFlatten<Int>())
You have to specify the type explicitly and you lose compile-time safety. But it can flatten lists of any nesting and with elements of different types ([1, "foo", [3, "bar"]] -> [ 1, "foo", 3, "bar"])
I would prefer a different solution. Something like this:
typealias It2<T> = Iterable<Iterable<T>>
typealias It3<T> = Iterable<It2<T>>
typealias It4<T> = Iterable<It3<T>>
typealias It5<T> = Iterable<It4<T>>
//etc...
fun <T> It3<T>.flatten2(): List<T> = flatten().flatten()
fun <T> It4<T>.flatten3(): List<T> = flatten2().flatten()
fun <T> It5<T>.flatten4(): List<T> = flatten3().flatten()
//etc...
...
println(data.flatten2())

Is there any replicate function in Kotlin?

replicate(n:Int,x:T):List<T> is a list of length n with x the value of every element.
I wrote a mutable version replicate as below:
fun <T> mutableReplicate(n:Int, x:T) : MutableList<T>{
val xs = mutableListOf<T>()
for (i in 1..n){
xs.add(x)
}
return xs
}
Is there any bulid-in immutable replicate function in Kotlin?
How to write ourselves an immutable replicate function in Kotlin?
You can use List instantiation functions. They accept a function from the Index to the desired element, but you can also use them to create a List of constant values.
fun <T> replicate(n:Int,x:T):List<T> {
return List(n) { x }
}
If you need a read-only list, you can implement replicate the following way:
fun <T> replicate(n: Int, x: T): List<T> = object : AbstractList<T>() {
override val size: Int = n
override fun get(index: Int): T =
if (index in 0..lastIndex) x else throw IndexOutOfBoundsException("$n")
}
It has an advantage that it requires a constant amount of memory no matter how large n is.

Is there a way to construct a HashSet with initializator function in Kotlin?

To read Stars from a file in the Facebook Hacker Cup's 2016 Boomerang Constelations problem, following extension function can be defined:
fun BufferedReader.readStars(n: Int): Set<Star> {
return Array(n) {
val (l1, l2) = readLine().split(" ").map { it.toInt() }
Star(l1, l2)
}.toHashSet()
}
Code is compact but the values are first read into an array and then converted to a HashSet. Is there a way to directly initialize a HashSet with the size of n and initializator function in Kotlin?
UPDATE: Is there an existing way in standard Kotlin libs?
You can always use apply to initialize objects in-place:
HashSet<Star>(n).apply {
repeat(n) {
val (l1, l2) = readLine()!!.split(' ').map { it.toInt() }
put(Star(l1, l2))
}
}
If that's too inconvenient too type every time, write an extension function:
inline fun <T> createHashSet(n : Int, crossinline fn: (Int) -> T) = HashSet<T>(n).apply {
repeat(n) { add(fn(it)) }
}
Usage:
createHashSet<Star>(n) {
val (l1, l2) = readLine()!!.split(' ').map { it.toInt() }
Star(l1, l2)
}
Since HashSet is a java class so you can only initialize it in a way provided by JDK.
While there's no helper method in Kotlin runtime it's easy to write it yourself like so:
public fun <T> hashSetOf(size: Int, initializer: (Int) -> T): HashSet<T> {
val result = HashSet<T>(size)
0.rangeTo(size - 1).forEach {
result.add(initializer(it))
}
return result
}
As #miensol has pointed out HashSet initialization is limited to the constructors made available by the JDK. Kotlin has added a hashSetOf function which initializes an empty HashSet and then adds the specified elements to it.
To avoid first reading the values into an array you can use a kotlin.Sequence who's "values are evaluated lazily":
fun BufferedReader.readStars(n: Int): Set<Star> {
return lineSequence().take(n).map {
val (l1, l2) = it.split(" ").map { it.toInt() }
Star(l1, l2)
}.toHashSet()
}
It seems like you are asking an XY question (http://xyproblem.info/). You really want to know how to write readStars in the most efficient way, but instead you ask about HashSet. I think #mfulton26 answers your question as well depending on what is being asked.
Here is the answer for "how do I write this in the most efficient way:"
You have two options. First, a version that auto-closes the stream at the end:
fun BufferedReader.readStars(n: Int): Set<Star> {
return use {
lineSequence().map { line ->
val idx = line.indexOf(' ')
Star(line.substring(0, idx).toInt(), line.substring(idx + 1).toInt())
}.toSet()
}
}
And second, a version that does not:
fun BufferedReader.readStars(n: Int): Set<Star> {
return lineSequence().map { line ->
val idx = line.indexOf(' ')
Star(line.substring(0, idx).toInt(), line.substring(idx+1).toInt())
}.toSet()
}
Neither version creates an array, neither do they make copies of data. They stream the data through a sequence which creates the Set and fills it directly.
Other notes
No need to use split if you are really concerned about allocations and performance. Just use indexOf(char) and split the string yourself using substring.
If you do a split, then please use split(char) not split(String) when you are looking to split on a char