Sorry this seems very basic but I'm missing something
I have a method signature override
fun doSomeWork (range: IntProgression, j: Int): List<Cell>{
I want to iterate the range whatever it is (could be up or down say 1 to 4 or 4 down to 1). The range itself seems to work, so on my 4 down to 1 example
println (range.first.toString() + " to " + range.last.toString() + ", step = " + range.step)
prints "4 to 1, step = 1"
but I can't seem to iterate the range ? I've tried a few things
for (i in range) {
println ("range: $i)"
}
and then
for (i in range.first until range.last step range.step){
println ("Loop de loop $i")
}
(although writing this question I noticed it is step 1 not -1 which may be the issue here ? but as I want to be able to pass in a range of either direction I haven't checked)
and then
range.forEach { println ("range foreach") }
none of them print anything, but they don't throw an error so any code after that runs through properly.
Can anyone point out why I'm failing to do this entry level task ?!
So you want an IntProgression from 4 to 1 with step -1, i.e. IntProgression.fromClosedRange(4, 1, -1) or better yet: 4.downTo(1). While you wrote your question you already realised the step... but the starting point isn't 1 then, but rather 4 ;-) With the downTo such problems will not arise, as the function takes care of the direction and it's also more readable then.
Note also that you can simply use reversed to reverse a progression:
range.reversed()
and either use it in a for-loop or with .forEach, etc.
So:
val range = IntProgression.fromClosedRange(1, 4, 1)
range.forEach(::print) // prints: 1234
range.reversed().forEach(::print) // prints: 4321
The forEach method can be used to iterate through the IntProgression. The it can be used to get the value or index.
fun doSomeWork (range: IntProgression) {
range.forEach {
println(it)
}
}
Invoking the above method:-
ClassName().doSomeWork(IntProgression.fromClosedRange(1,10, 1))
val range= IntProgression.fromClosedRange(1, 4, 1)
for (i in range)
println(i) // out put 1234
for (i in range.reversed())
println(i)//out put 4321
use
IntProgression.fromClosedRange(start, end, step)
for reverse range
IntProgression.reversed()
more details refer Ranges
Related
In java I got this construction
for (let i = 0; i < x.length-1; I++
And here to avoid outOfBoundsException we are using x.length-1 but how to do the same thing in Kotlin? I got this code so far
x.forEachIndexed { index, _ ->
output.add((x[index+1]-x[index])*10)
}
And it crashes on the last element when we call x[index+1] so I need to handle the last element somehow
Input list
var x = doubleArrayOf(0.0, 0.23, 0.46, 0.69, 0.92, 1.15, 1.38, 1.61)
For a classic Java for loop you got two options in Kotlin.
One would be something like this.
val x = listOf(1,2,3,4)
for (i in 0 .. x.lastIndex){
// ...
}
Using .. you basically go from 0 up to ( and including) the number coresponding to the second item, in this case the last index of the list.( so from 0 <= i <= x.lastIndex)
The second option is using until
val x = listOf(1,2,3,4)
for (i in 0 until x.size){
// ...
}
This is similar to the previous approach, except the fact that until is not inclusive with the last element.(so from 0 <= i < x.size ).
What you probably need is something like this
val x = listOf(1,2,3,4)
for (i in 0 .. x.lastIndex -1){
// ...
}
or alternative, using until, like this
val x = listOf(1,2,3,4)
for (i in 0 until x.size-1){
// ...
}
This should probably avoid the IndexOut of bounds error, since you go just until the second to last item index.
Feel free to ask more if something is not clear.
This is also a great read if you want to learn more about ranges. https://kotlinlang.org/docs/ranges.html#progression
You already have an answer, but this is another option. If you would use a normal list, you would have access to zipWithNext(), and then you don't need to worry about any index, and you can just do:
list.zipWithNext { current, next ->
output.add((next - current)*10)
}
As mentioned by k314159, we can also do asList() to have direct access to zipWithNext and other list methods, without many drawbacks.
array.asList().zipWithNext { current, next ->
output.add(next - current)
}
I have a function generating values. It does so by recursively calling itself, and whenever the base case is reached, a value is emitted. This is just a toy example, the real one is much more complicated, and thus harder to transform to something non-recursive.
I would like to do this as a sequence. But doing this won't compile on the line I yield, with the message
Suspension functions can be called only within coroutine body
Here's the attempt:
fun test1() = sequence {
fun a(i: Int) {
if (i > 4) {
yield(i) // <- fails to compile
} else {
a(i + 1)
a(i + 2)
a(i + 3)
}
}
a(1)
}
If I try to add the suspend keyword to function a, I instead get the error
Restricted suspending functions can only invoke member or extension suspending functions on their restricted coroutine scope
I can make it work, by instead returning all the values and doing a yieldAll. The problem with this, however, is that it needs to do the whole computation and hold all the results in memory before the sequence can be used. For my case, this won't work as I'd run out of memory, or may even have an almost infinite amount of results where I only want to take a few.
So this works, but is not optimal
fun test2() = sequence {
fun a(i: Int): List<Int> {
if (i > 4) {
return listOf(i)
} else {
return listOf(
a(i + 1),
a(i + 2),
a(i + 3)
).flatten()
}
}
yieldAll(a(1))
}
Any ideas on how to combine sequences with a recursive function, allowing me to yield values without pre-computing and allocating memory for all of them?
How about making a return a lazy Sequence?
fun a(i: Int): Sequence<Int> =
sequence {
if (i > 4) {
// println("yielding $i")
yield(i)
} else {
yieldAll(a(i + 1)) // this yieldAll is lazy
yieldAll(a(i + 2))
yieldAll(a(i + 3))
}
}
fun test1() = a(1)
If you uncomment the println, and loop over the sequence, you will see that it is indeed lazy:
for (i in test1()) {
println("printing $i")
}
Output:
yielding 5
printing 5
yielding 6
printing 6
yielding 7
printing 7
yielding 5
printing 5
yielding 6
printing 6
yielding 5
printing 5
yielding 6
printing 6
yielding 7
printing 7
...
You can make the inner function a suspend function that is an extension of SequenceScope. The Sequence builder uses a special kind of coroutine that's limited to only calling suspend function extensions of SequenceScope. Presumably this is because Sequences are intended to be used only as synchronous, non-suspending iterables. Since yield() is one of these SequenceScope suspend functions, you have to make your function also a suspend extension function.
fun test1() = sequence {
suspend fun SequenceScope<Int>.a(i: Int) {
if (i > 4) {
yield(i)
} else {
a(i + 1)
a(i + 2)
a(i + 3)
}
}
a(1)
}
How one may count how many times specific character appears in string in Kotlin?
From looking at https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/ there is nothing built-in and one needs to write loop every time (or may own extension function), but maybe I missed a better way to achieve this?
Easy with filter {} function
val str = "123 123 333"
val countOfSymbol = str
.filter { it == '3' } // 3 is your specific character
.length
println(countOfSymbol) // output 5
Another approach
val countOfSymbol = str.count { it == '3'} // 3 is your specific character
println(countOfSymbol) // output 5
From the point of view of saving computer resources, the count decision(second approach) is more correct.
I am pretty confused with both functions fold() and reduce() in Kotlin, can anyone give me a concrete example that distinguishes both of them?
fold takes an initial value, and the first invocation of the lambda you pass to it will receive that initial value and the first element of the collection as parameters.
For example, take the following code that calculates the sum of a list of integers:
listOf(1, 2, 3).fold(0) { sum, element -> sum + element }
The first call to the lambda will be with parameters 0 and 1.
Having the ability to pass in an initial value is useful if you have to provide some sort of default value or parameter for your operation. For example, if you were looking for the maximum value inside a list, but for some reason want to return at least 10, you could do the following:
listOf(1, 6, 4).fold(10) { max, element ->
if (element > max) element else max
}
reduce doesn't take an initial value, but instead starts with the first element of the collection as the accumulator (called sum in the following example).
For example, let's do a sum of integers again:
listOf(1, 2, 3).reduce { sum, element -> sum + element }
The first call to the lambda here will be with parameters 1 and 2.
You can use reduce when your operation does not depend on any values other than those in the collection you're applying it to.
The major functional difference I would call out (which is mentioned in the comments on the other answer, but may be hard to understand) is that reduce will throw an exception if performed on an empty collection.
listOf<Int>().reduce { x, y -> x + y }
// java.lang.UnsupportedOperationException: Empty collection can't be reduced.
This is because .reduce doesn't know what value to return in the event of "no data".
Contrast this with .fold, which requires you to provide a "starting value", which will be the default value in the event of an empty collection:
val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)
So, even if you don't want to aggregate your collection down to a single element of a different (non-related) type (which only .fold will let you do), if your starting collection may be empty then you must either check your collection size first and then .reduce, or just use .fold
val collection: List<Int> = // collection of unknown size
val result1 = if (collection.isEmpty()) 0
else collection.reduce { x, y -> x + y }
val result2 = collection.fold(0) { x, y -> x + y }
assertEquals(result1, result2)
Another difference that none of the other answers mentioned is the following:
The result of a reduce operation will always be of the same type (or a super type) as the data that is being reduced.
We can see that from the definition of the reduce method:
public inline fun <S, T : S> Iterable<T>.reduce(operation: (acc: S, T) -> S): S {
val iterator = this.iterator()
if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
var accumulator: S = iterator.next()
while (iterator.hasNext()) {
accumulator = operation(accumulator, iterator.next())
}
return accumulator
}
On the other hand, the result of a fold operation can be anything, because there are no restrictions when it comes to setting up the initial value.
So, for example, let us say that we have a string that contains letters and digits. We want to calculate the sum of all the digits.
We can easily do that with fold:
val string = "1a2b3"
val result: Int = string.fold(0, { currentSum: Int, char: Char ->
if (char.isDigit())
currentSum + Character.getNumericValue(char)
else currentSum
})
//result is equal to 6
reduce - The reduce() method transforms a given collection into a single result.
val numbers: List<Int> = listOf(1, 2, 3)
val sum: Int = numbers.reduce { acc, next -> acc + next }
//sum is 6 now.
fold - What would happen in the previous case of an empty list? Actually, there’s no right value to return, so reduce() throws a RuntimeException
In this case, fold is a handy tool. You can put an initial value by it -
val sum: Int = numbers.fold(0, { acc, next -> acc + next })
Here, we’ve provided initial value. In contrast, to reduce(), if the collection is empty, the initial value will be returned which will prevent you from the RuntimeException.
Simple Answer
Result of both reduce and fold is "a list of items will be transformed into a single item".
In case of fold,we provide 1 extra parameter apart from list but in case of reduce,only items in list will be considered.
Fold
listOf("AC","Fridge").fold("stabilizer") { freeGift, itemBought -> freeGift + itemBought }
//output: stabilizerACFridge
In above case,think as AC,fridge bought from store & they give stabilizer as gift(this will be the parameter passed in the fold).so,you get all 3 items together.Please note that freeGift will be available only once i.e for the first iteration.
Reduce
In case of reduce,we get items in list as parameters and can perform required transformations on it.
listOf("AC","Fridge").reduce { itemBought1, itemBought2 -> itemBought1 + itemBought2 }
//output: ACFridge
The difference between the two functions is that fold() takes an initial value and uses it as the accumulated value on the first step, whereas the first step of reduce() uses the first and the second elements as operation arguments on the first step.
When normally using a for-in-loop, the counter (in this case number) is a constant in each iteration:
for number in 1...10 {
// do something
}
This means I cannot change number in the loop:
for number in 1...10 {
if number == 5 {
++number
}
}
// doesn't compile, since the prefix operator '++' can't be performed on the constant 'number'
Is there a way to declare number as a variable, without declaring it before the loop, or using a normal for-loop (with initialization, condition and increment)?
To understand why i can’t be mutable involves knowing what for…in is shorthand for. for i in 0..<10 is expanded by the compiler to the following:
var g = (0..<10).generate()
while let i = g.next() {
// use i
}
Every time around the loop, i is a freshly declared variable, the value of unwrapping the next result from calling next on the generator.
Now, that while can be written like this:
while var i = g.next() {
// here you _can_ increment i:
if i == 5 { ++i }
}
but of course, it wouldn’t help – g.next() is still going to generate a 5 next time around the loop. The increment in the body was pointless.
Presumably for this reason, for…in doesn’t support the same var syntax for declaring it’s loop counter – it would be very confusing if you didn’t realize how it worked.
(unlike with where, where you can see what is going on – the var functionality is occasionally useful, similarly to how func f(var i) can be).
If what you want is to skip certain iterations of the loop, your better bet (without resorting to C-style for or while) is to use a generator that skips the relevant values:
// iterate over every other integer
for i in 0.stride(to: 10, by: 2) { print(i) }
// skip a specific number
for i in (0..<10).filter({ $0 != 5 }) { print(i) }
let a = ["one","two","three","four"]
// ok so this one’s a bit convoluted...
let everyOther = a.enumerate().filter { $0.0 % 2 == 0 }.map { $0.1 }.lazy
for s in everyOther {
print(s)
}
The answer is "no", and that's a good thing. Otherwise, a grossly confusing behavior like this would be possible:
for number in 1...10 {
if number == 5 {
// This does not work
number = 5000
}
println(number)
}
Imagine the confusion of someone looking at the number 5000 in the output of a loop that is supposedly bound to a range of 1 though 10, inclusive.
Moreover, what would Swift pick as the next value of 5000? Should it stop? Should it continue to the next number in the range before the assignment? Should it throw an exception on out-of-range assignment? All three choices have some validity to them, so there is no clear winner.
To avoid situations like that, Swift designers made loop variables in range loops immutable.
Update Swift 5
for var i in 0...10 {
print(i)
i+=1
}