Reputation: 47
I am trying to create a function that will return another function that will do multiple string operations (as determined by the given options):
The options are U
(uppercase), l
(lowercase) T
(title case) s
(sorted) r
(reverse) and *
(remove all whitespace).
Right now, the code I have will take one of the options above (so, either U
or s
, etc) and return the correct result. What I want is that stringPipeline("Us*")
should return a function that will convert string to uppercase, sort it and remove all whitespace.
I can't figure out how to modify my function to accommodate multiple options.
def stringPipeline(Option:String) = (str:String) => {
val UpperCase = () => str.toUpperCase
val LowerCase = () => str.toLowerCase
val titleCase = () => str.split(' ').map(_.capitalize).mkString(" ")
val reverse = () => str.reverse
val sortChars = () => str.sorted
val replaceChar = () => str.replaceAll("\\s","")
Option match {
case "U" => UpperCase()
case "l" => LowerCase()
case "T" => titleCase()
case "r" => reverse()
case "s" => sortChars()
case "*" => replaceChar()
}
}
I've tried using &&
operator (didn't work), +
operator (called both functions) and doing something like reverse(UpperCase())
which gave a compiler error.
Upvotes: 3
Views: 503
Reputation: 993
An alternate approach would be to generate a composite function. You can try andThen to compose functions. For example:
scala> def inputStringPipeline(inputStr: String): String => String = {
| val upperCase = (input: String) => input.toUpperCase
| val lowerCase = (input: String) => input.toLowerCase
| val titleCase = (input: String) => input.split(' ').map(_.capitalize).mkString(" ")
| val reverse = (input: String) => input.reverse
| val sortChars = (input: String) => input.sorted
| val replaceChar = (input: String) => input.replaceAll("\\s", "")
|
| val emptyFunc: String => String = (input: String) => input
| inputStr.foldLeft(emptyFunc) {
| case (funcAcc, present) =>
| val newFunc = present.toString match {
| case "U" => upperCase
| case "l" => lowerCase
| case "T" => titleCase
| case "r" => reverse
| case "s" => sortChars
| case "*" => replaceChar
| }
|
| funcAcc andThen newFunc
| }
|
| }
inputStringPipeline: (inputStr: String)String => String
scala> val input = "Us*"
input: String = Us*
scala> val func = inputStringPipeline(input)
func: String => String = scala.Function1$$Lambda$1061/1593722877@5ef7ae2f
scala> val str = func("age bfh dc")
str: String = ABCDEFGH
scala> println(str)
ABCDEFGH
This way a new function would be generated for a given input string operation and can be used with any number of strings. This would save time by creating the composite function once and using it again.
Upvotes: 0
Reputation: 28322
You could use foldLeft
to recursively apply all operators on the string using a separate function that takes one option at the time.
def stringPipeline(ops: String) = (str: String) => {
def applyOp(str: String, op: String) = op match {
case "U" => str.toUpperCase
case "l" => str.toLowerCase
case "T" => str.split(' ').map(_.capitalize).mkString(" ")
case "r" => str.reverse
case "s" => str.sorted
case "*" => str.replaceAll("\\s","")
}
ops.split("").foldLeft(str)(applyOp)
}
Testing with a string:
val str = stringPipeline("Us*")("age bfh dc")
println(str)
will give the expected result
ABCDEFGH
Upvotes: 3