9

In this code I want to increment index to put it to each yielding 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?

ses
  • 13,174
  • 31
  • 123
  • 226

4 Answers4

25

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)
Ben James
  • 121,135
  • 26
  • 193
  • 155
6

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.

Community
  • 1
  • 1
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
  • yep. that was stupid fro my side. at least I'm glad that no surprise from yield. (I just put it because I want to start from 0-index). I tent to think that something goes not right way because of scala but not me :). but this differennt case %) there are many surprises I've got recently.. that's why – ses Jun 02 '13 at 14:54
3

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 )
}
Max
  • 2,065
  • 24
  • 20
  • 1
    this will go go though whole list all the time to get the item by index: strs(i). might be slow. – ses Jun 03 '13 at 18:13
  • updated answer. Sequence need to be indexed in order to provide a good random access performance. – Max Jun 05 '13 at 03:47
1
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.

Jatin
  • 31,116
  • 15
  • 98
  • 163