I want to apply a condition using higher-order infix extension function on a list of pair. I want my condition to show me the first numbers of the pair. Specifically, show those first numbers whose sum with their second number is 5.
T
this is the code I have written so far
fun main() {
infix fun List<Pair<Int,Int>>.takeFirstsBy(
condition: // i need help in this line to apply a condition on list of pair
):List<Int>{
}
}
I don't know how to write a conditional statement to apply to pairs after the (condition) statement please help me. Thanks
CodePudding user response:
You don't write the condition
but the invoker does.
condition: (Pair<Int, Int>) -> Boolean
We need an argument Pair<Int, Int>
because is the item of the list, so you call it on the iterator you use.
infix fun List<Pair<Int,Int>>.takeFirstsBy(
condition: (Pair<Int, Int>) -> Boolean
):List<Int>{
return this.mapNotNull {
if (condition.invoke(it)) {
//pair.first or pair.second ?
} else null //null won't be included
}
}
And then you call it like this
So the iterator runs through the list and filter the thing on the condition
list.takeFirstBy { pair: Pair<Int, Int> ->
//implement the condition here
}
CodePudding user response:
There's no reason to make a higher order function infix, because of trailing lambda syntax. All it would do is allow you to replace the dot with a space, and make the code harder to read because it differs from conventional syntax. Also, higher order functions on collections are often chained from line to line, and you can only do this by using dot notation.
It would make sense to make it inline
though, so the lambda doesn't have to be allocated each time you call this function.
You can make the receiver type an Iterable to make the function more versatile.
Your conditional has an input of a Pair of Ints, and needs to return a Boolean, so the signature is (Pair<Int, Int>) -> Boolean
.
The logic of your function is to filter to only the ones that pass the condition, and then to map that filtered result to show only the first number of the pair.
inline fun Iterable<Pair<Int,Int>>.takeFirstsBy(
condition: (Pair<Int,Int>)->Boolean
):List<Int>{
return filter(condition).map { it.first }
}
fun main() {
val input = listOf(1 to 4, 2 to 3, 5 to 5)
val result = input.takeFirstsBy { it.first it.second == 5 }
println(result)
}
Alternate implementation. I think this is less readable, but it is more efficient:
inline fun Iterable<Pair<Int,Int>>.takeFirstsBy(
condition: (Pair<Int,Int>)->Boolean
):List<Int>{
return mapNotNull { it.takeIf(condition)?.first }
}