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?

4 Answers 4

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)
Sign up to request clarification or add additional context in comments.

2 Comments

That's nice. I've already seen this kind of transformation. But it still in passive knowledge. That's concise indeed.
wouldn't that be inefficient?
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.

1 Comment

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

2 Comments

this will go go though whole list all the time to get the item by index: strs(i). might be slow.
updated answer. Sequence need to be indexed in order to provide a good random access performance.
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.

1 Comment

Code like this could easily use some explanatory words to go with it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.