Is there a Kotlin equivalent for Groovy's findIndexValues? - kotlin

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 }

Related

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())

Idiomatic way of finding by value predicate on a Map

What is the best way to search a map and find the first key that matches a predicate on value or null otherwise? My code below looks too verbose for kotlin standard. Please help.
fun <K, V> find(map : Map<K, V?>, predicate: (V?) -> Boolean): K? {
var key : K? = null
map.forEach { it ->
if(predicate(it.value)) {
key = it.key
return#forEach
}
}
return key
}
map.entries.firstOrNull { predicate(it.value) }?.key
entries is used to make the Map iterable, and is "free" (in that it doesn't require iterating over the map). Of course, it enables all collection extension functions missing on Map itself, not just firstOrNull.
(You can also replace firstOrNull with find; they are equivalent here.)
You don't need var key, you can instead immediately return the key once found and return null in the end.
In the lambda passed to forEach, you can use parameter destructuring to access the key and value without using it:
fun <K, V> find(map : Map<K, V?>, predicate: (V?) -> Boolean): K? {
map.forEach { (key, value) ->
if (predicate(value)) {
return key
}
}
return null
}
Also, you can convert the map parameter to receiver, making it an extension function that can be called on a map instance:
fun <K, V> Map<K, V>.findKeyByValue(predicate: (V) -> Boolean): K? {
forEach { (key, value) ->
if (predicate(value)) {
return key
}
}
return null
}
val result = myMap.findKeyByValue { it > 0 }
You can use filter for search a map and find the first key
for example
var arr = mutableMapOf<Any, Any>()
arr.put("1", "dax1")
arr.put("2", "dax2")
arr.put("3", "dax3")
arr.put("4", "dax4")
val key = arr.filter {
it.value.equals("dax5")
}.keys
if (key.isNotEmpty()) {
Log.e("key", key.elementAt(0).toString())
} else {
Log.e("key", "Key not found")
}
Hope this will help you
Use a combination of filter and firstOrNull
val firstKey = map.keys.filter { it == 1 }.firstOrNull()
To make it lazy, convert it to a sequence before:
val firstKey = map.keys.asSequence().filter { it == 1 }.firstOrNull()

how to implement an applyif for Kotlin?

I'd like to have an applyif to work like:
builder.applyif(<condition expression>) {
builder.set...
}
to be equal with:
builder.apply {
if (<condition expression>) {
builder.set...
}
}
Is that possible?
Yes, of course. You can nearly program anything, but don't reinvent the wheel. Look at the bottom of the answer to see a standard Kotlin approach without own extension function(s) which may already suffice your needs (not exactly applyIf though).
Now, however, lets see how an applyIf might be implemented:
inline fun <T> T.applyIf(predicate: T.() -> Boolean, block: T.() -> Unit): T = apply {
if (predicate(this))
block(this)
}
Don't forget the inline if you are implementing extension functions with lambdas.
Here is an example usage of the above.
// sample class
class ADemo {
fun isTrue() = true
}
// sample usage using method references
ADemo().applyIf(ADemo::isTrue, ::println)
// or if you prefer or require it, here without
ADemo().applyIf( { isTrue() } ) {
println(this)
}
If you just want to supply a boolean instead, you can use the following extension function:
inline fun <T> T.applyIf(condition : Boolean, block : T.() -> Unit) : T = apply {
if(condition) block(this)
}
and call it with:
val someCondition = true
ADemo().applyIf(someCondition) {
println(this)
}
And now a possible Kotlin standard way with which more people could be familiar:
ADemo().takeIf(ADemo::isTrue)
?.apply(::println)
// or
ADemo().takeIf { it.isTrue() }
?.apply { println(this) }
If they do remember (I actually didn't until I saw Marko Topolniks comment) they should immediately know what's going on.
However, if you require the given value (i.e. ADemo()) after calling takeIf this approach might not work for you as the following will set the variable to null then:
val x = ADemo().takeIf { false }
?.apply { println(this) /* never called */ }
// now x = null
whereas the following will rather set the variable to the ADemo-instance:
val x = ADemo().applyIf(false) { println(this) /* also not called */ }
// now x contains the ADemo()-instance
Chaining the builder calls might not be so nice then. Still you can also accomplish this via standard Kotlin functions by combining the takeIf with apply or also (or with, let, run, depending on whether you want to return something or not or you prefer working with it or this):
val x = builder.apply {
takeIf { false }
?.apply(::println) // not called
takeIf { true }
?.apply(::println) // called
}
// x contains the builder
But then again we are nearly there where you were already in your question. The same definitely looks better with applyIf-usage:
val x = builder.applyIf(false, ::println) // not called
.applyIf(true) {
println(this) // called
}
// x contains the builder
Sure you can, you just need an extension function so you can call it on the builder, and you need it to take a Boolean parameter and the lambda to execute.
If you look at the source of the apply function itself, it will help with most of the implementation:
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
Based on this, applyIf can be as simple as:
inline fun <T> T.applyIf(condition: Boolean, block: T.() -> Unit): T {
return if (condition) this.apply(block) else this
}
Usage looks like this:
builder.applyIf(x > 200) {
setSomething()
}
fun <T> T.applyIf(condition: Boolean, block: T.() -> T) = if (condition) block() else this
fun main() {
println("a".applyIf(true) { uppercase() }) // A
println("a".applyIf(false) { uppercase() }) // a
}

Kotlin smart cast the second value of a pair with filter

I'm trying to write a function that maps a String and Int? into a pair, then filters for non null second values in the pair, before continuing to map.
My code looks like this:
val ids: List<String> = listOf("a", "b", "c")
val ints: Map<String, Int?> = mapOf("a" to 1, "b" to 2, "c" to null)
ids.map { id: String ->
Pair(id, ints[id])
}.filter { pair -> pair.second != null}.map { pair: Pair<String, Int> ->
func(id, pair.second)
}
The problem is that the second map has the error:
Type inference failed: Cannot infer type parameter T in
inline fun <T, R> kotlin.collections.Iterable<T>.map ( transform (T) -> R ): kotlin.collections.List<R>
This looks like because the compiler does not know to smart cast my Iterable<Pair<String, Int?>> into an Iterable<Pair<String, Int>> after my filter. What can I do instead to solve this?
Kotlin's smart cast is usually not applicable outside method boundaries. However, there are a couple of ways you can achieve your goal anyway.
First, you can simply tell the compiler that the second value of the pair is never null by using the !! operator like so:
ids.map { id: String -> Pair(id, ints[id]) }
.filter { pair -> pair.second != null }
.map { pair: Pair<String, Int?> -> func(pair.second!!) }
Second, you can reverse the order of filter and map and apply the !! operator earlier:
ids.filter { id: String -> ints[id] != null }
.map { id: String -> id to ints[id]!! } //equivalent to Pair(id, ints[id]!!)
.map { pair: Pair<String, Int> -> func(pair.second) }
Finally, you can make it work without the !! operator by combining the filtering and the mapping in one step using the mapNotNull extension method:
ids.mapNotNull { id: String -> ints[id]?.let { id to it } }
.map { pair: Pair<String, Int> -> func(pair.second) }

Is there a less ugly way to return function in Kotlin?

This declaration works, but is not the most beautiful code. Is there a way to return functions less ugly? I tried (s: String) -> writer.println(s) but this didn't work.
val writeStuff: (PrintWriter) -> (String) -> Unit = {
val writer = it
val f: (String) -> Unit = {
writer.println(it)
}
f
}
PrintWriter("test").use { writeStuff(it)("TEST") }
EDIT: a bit more concrete example:
val writeStuff: (PrintWriter) -> (String) -> Unit = { writer ->
{ writer.println(it) }
}
val sendStuff: (Any) -> (String) -> Unit = { sender ->
{ sender.equals(it) }
}
#Test fun test1() {
val li = listOf("a", "b", "c")
val process: List<(String) -> Unit> =
listOf(writeStuff(PrintWriter("a")), sendStuff(Object()))
process.map { li.map(it) }
}
First, you can simplify your code using lambda syntax with explicit parameter and inlining val f:
val writeStuff: (PrintWriter) -> (String) -> Unit = { writer ->
{ writer.println(it) }
}
But since Kotlin supports local function declarations, you can even make writeStuff a local fun instead of a val.
This would lead to the following code:
fun writeStuff(writer: PrintWriter): (String) -> Unit {
return { writer.println(it) }
}
Or, using the single expression syntax,
fun writeStuff(writer: PrintWriter): (String) -> Unit = { writer.println(it) }
The usage, however, will be the same:
PrintWriter("...").use { writeStuff(it)("...") }
I stumbled across this question while trying to figure out how to return a Function (the java interface) in Kotlin. While this doesn't directly answer the question, hopefully it'll help someone else who has the same query:
override fun myFun(param1: Object): Function<in Object, out String?> {
if (!param1.meetsCriteria())
return Function { obj -> null }
return Function { obj ->
"success"
}
}
In this case, I was overriding a method in a java interface that required me to return a Function instance. (Note that since the param is not used in my particular implementation above, I could remove it and just have the return result. eg return Function { null })
Edit: After some research, it turns out Kotlin covers this subject with their discussion on "SAM (single abstract method) conversions" here and here, though it may not be the most intuitive thing to look up when figuring out how to return Functions.