In this code I want to increment index
to put it to each yield
ing result.
var index=0
for(str <- splitToStrings(text) ) yield {
if (index != 0) index += 1 // but index is equal to `0` all the time
new Word(str, UNKNOWN_FORM, index )
}
Why I can not change index
? And what the best way to implement this logic then, trying to be concise?
The index value represents the number of the currently executing iteration. More specifically, the body of the loop (the instructions that are executed during each loop repetition) can be said to be iterated as the loop executes.
The zipWithIndex function is applicable to both Scala's Mutable and Immutable collection data structures. The zipWithIndex method will create a new collection of pairs or Tuple2 elements consisting of the element and its corresponding index. The zipWithIndex method is a member of IterableLike trait.
In Scala, the loop's return value is stored in a variable or may return through a function. To do this, you should prefix the body of the 'for' expression with the keyword yield.
The zipWithIndex
method on most sequence-like collections will give you a zero-based index, incrementing with each element:
for ((str, index) <- splitToStrings(text).zipWithIndex)
yield new Word(str, UNKNOWN_FORM, index)
Because initially index is set to 0, thus your condition index != 0
is never executes to true and index is never got incremented. Maybe you don't need this condition? Maybe you can count results afterwards? Now I see that index is used within loop. Then you have to either use @BenJames answer or go recursive.
zipWithIndex
will copy and create a new collection, so better make it lazy when the collection is potentially large
for ((str, index) <- splitToStrings(text).view.zipWithIndex)
yield new Word(str, UNKNOWN_FORM, index)
In fact, if you are working with an indexed sequence, then a more efficient way is to use indices
, which produces the range of all indices of this sequence.
val strs = splitToStrings(text)
for(i <- strs.indices) yield {
new Word(strs(i), UNKNOWN_FORM, i )
}
splitToStrings(text).foldLeft(0,List[Word]){(a,b) => {
if(a._1!=0) (a._1+1,new Word(str, UNKNOWN_FORM, index) :: b)
else (a._1,new Word(str, UNKNOWN_FORM, index) :: b)
}}
I am using foldLeft
here with a tuple as: starting base with index = 0
and an empty List
. I then iterate over each element.
Above a
is this tuple. I check the index
value and increment it. Else I dont add the index
. And I add the new Word
to the list.
Ultimately in the end you get a tuple containing the index value and the total List containing all Words.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With