1

For example I want to encrypt each token of a sentence and reduce them to a final encrypted text:

def convert(str: String) = {
  str + ":"
}

val tokens = "Hi this is a text".split("\\ ").toList

val reduce = tokens.reduce((a, b) => convert(a) + convert(b))
println(reduce)
// result is `Hi:this::is::a::text:`

val fold = tokens.fold("") {
  case (a, b) => convert(a) + convert(b)
}
println(fold)
// result is `:Hi::this::is::a::text:`

val scan = tokens.scan("") {
  case (a, b) => convert(a) + convert(b)
}
println(scan)
// result is List(, :Hi:, :Hi::this:, :Hi::this::is:, :Hi::this::is::a:, :Hi::this::is::a::text:)

Assume that convert is an encryption function. So each token should encrypt only once not twice. but fold and reduce and scan reencrypt the encrypted token. I want this desired result Hi:this:is:a:text:

Pooya
  • 4,385
  • 6
  • 45
  • 73
  • In all these cases you seem to be assuming that a and b are the same. They're not. a is the accumulated result, and b the next token. So you're encrypting the token (b) and adding it to the result, and next time re-encrypting that result. So miss the convert of a out and things will look a lot better! – The Archetypal Paul Jan 21 '14 at 09:51

5 Answers5

2

Well if you want to encrypt each Token individually, map should work.

val tokens = "Hi this is a text".split("\\ ").toList

val encrypted = tokens.map(convert).mkString

println(encrypted) //prints Hi:this:is:a:text:

def convert(str: String) = {
  str + ":"
}

Edit: If you want to use a fold:

val encrypted = tokens.foldLeft("")((result, token) => result + convert(token))
Kigyo
  • 5,668
  • 1
  • 20
  • 24
2

One-liner specialised at this very example,

"Hi this is a text" split " " mkString("",":",":")

Or

val tokens = "Hi this is a text" split " "
val sep = ":"
val encrypted = tokens mkString("",sep,sep)
elm
  • 20,117
  • 14
  • 67
  • 113
2

Note that fold or reduce will operate on two operands in every step. However you want to encrypt each of the tokens -- which is a unary operand. Therefore first you should do a map and then either a fold or a reduce:

tokens map(convert)

Reduce / Fold:

scala> tokens.map(convert).fold("")(_ + _)
res10: String = Hi:this:is:a:text:

scala> tokens.map(convert)reduce(_ + _)
res11: String = Hi:this:is:a:text:

Infact you can simply use mkString which makes it even more concise:

scala> tokens.map(convert).mkString
res12: String = Hi:this:is:a:text:

Also you can do the conversion in parallel too (using par ):

scala> tokens.par.map(convert).mkString
res13: String = Hi:this:is:a:text:

scala> tokens.par.map(convert)reduce(_ + _)
res14: String = Hi:this:is:a:text:
tuxdna
  • 8,257
  • 4
  • 43
  • 61
1

I think your main problem is how reduce and fold works. You can learn from other answer

As for you question, fold can help:

"Hi this is a text".split("\\ ").fold("") { (a, b) => a + convert(b) }
Community
  • 1
  • 1
Windor C
  • 1,120
  • 8
  • 17
1

Here is a version with the code cleaned up and unnecessary conversions removed:

def convert(str: String) = str + :

val tokens = "Hi this is a text" split " "
val encrypted = (tokens map convert) mkString " "

mkString could be seen as a specialized Version of reduce (or fold) for Strings.

If for some reason, you don't want to use mkString the code would look like this:

def convert(str: String) = str + :

val tokens = "Hi this is a text" split " "
val encrypted = (tokens map convert) reduce (_ + _)

Or shortend with fold

val encrypted = "Hi this is a text".split(" ").foldLeft ("") { case (accum, str) => accum + convert(str) }
Andreas Neumann
  • 10,734
  • 1
  • 32
  • 52