I am using the play framework 2.2.1 and I have a question concerning the manipulation of Strings within view templates. Unfortunately I am not very familiar with the Scala programming language nor its APIs. The strings are contained in a List which is passed from the controller to the view and then I use a loop to process each string before they are added to the html. I would like to know how to do the following: trim, toLowerCase and remove spaces. As an example, if I have "My string ", I would like to produce "mystring". More specifically I would actually like to produce "myString", however I'm sure I can figure that out if someone points me in the right direction. Thanks.
UPDATE:
Fiaz provided a great solution, building on his answer and just for interest sake I came up with the following solution using recursion. This example is of course making many assumptions about the input provided.
#formatName(name: String) = #{
def inner(list: List[String], first: Boolean): String = {
if (!list.tail.isEmpty && first) list.head + inner(list.tail, false)
else if (!list.tail.isEmpty && !first) list.head.capitalize + inner(list.tail, false)
else if (list.tail.isEmpty && !first) list.head.capitalize
else list.head
}
if (!name.trim.isEmpty) inner(name.split(' ').map(_.toLowerCase).toList, true)
else ""
}
If you want to know how to do just the trimming, lower-casing and joining without spaces, try this perhaps?
// Given that s is your string
s.split(" ").map(_.toLowerCase).mkString
That splits a string into an array strings, splitting is done on one or more spaces so that gives you trimmed strings. You then map each element in the array with the function (x => x.toLowerCase) (for which the shorthand is (_.toLowerCase)) and then join the Array back into a single string using the mkString method that collections have.
So let's say you want to capitalize the first letter of the each of the space-split bits:
Scala provides a capitalize method on Strings, so you could use that:
s.split(" ").map(_.toLowerCase.capitalize).mkString
See http://www.scala-lang.org/api/current/scala/collection/immutable/StringOps.html
One suggestion as to how you can get the exact output (your example 'myString') you describe:
(s.split(" ").toList match {
case fst::rest => fst.toLowerCase :: rest.map(_.toLowerCase.capitalize)
case Nil => Nil }
).mkString
There is example of using the string manipulation below:
#stringFormat(value: String) = #{
value.replace("'", "\\'")
}
#optionStringFormat(description: Option[String]) = #{
if (description.isDefined) {
description.get.replace("'", "\\'").replace("\n", "").replace("\r", "")
} else {
""
}
}
#for(photo <- photos) {
<div id="photo" class="random" onclick="fadeInPhoto(#photo.id, '#photo.filename', '#stringFormat(photo.title)', '#optionStringFormat(photo.description)', '#byTags');">
This example obtained from https://github.com/joakim-ribier/play2-scala-gallery
Related
So the idea here is that I'm taking a .csv into a string and each value needs to be stored into a variable. I am unsure how to properly parse a string to do this.
My idea is a function that looks like
final char delim = ',';
int nextItem(String data, int startFrom) {
if (data.charAt(startFrom) != delim) {
return data.charAt(startFrom)
} else {
return nextItem(data, startFrom + 1);
}
}
so if I passed it something like
nextItem("45,621,9", 0);
it would return 45
and if I passed it
nextItem("45,621,9", 3);
it would return 621
I'm not sure if I have that setup properly to be recursive, but I could also use a For loop I suppose, only real stipulation is I can't use the Substring method.
Please don't use recursion for a matter that can be easily done iteratively. Recursion is expensive in terms of stack and calling frames: A very long string could produce a StackOverflowError.
I suggest you take a look to standard method indexOf of java.lang.String:
A good alternative is Regular Expressions.
You can seperate the words considering comma ',' as delimeter
Code
String[] nextItem(String data) {
String[] words=data.split(",");
return words;
}
This will return an array of strings that is the words in your input string. Then you can use the array in anyway you need.
Hope it helps ;)
Processing comes with a split() function that does exactly what you're describing.
From the reference:
String men = "Chernenko,Andropov,Brezhnev";
String[] list = split(men, ',');
// list[0] is now "Chernenko", list[1] is "Andropov"...
Behind the scenes it's using the String#split() function like H. Sodi's answer, but you should just use this function instead of defining your own.
So I am learning Kotlin now, and I was trying to do a calculator where if we can give expression like 4+3 or 3*5 and we will get the answer so I was trying to split that input string and then find what operator is used and what are the operands.
var list = str.split("+","-","*","/" )
so how can i get the delimiter that is used to split that string too.
I'm afraid that split method doesn't have this feature. You would have to split the the string via separate split calls. And compare the outcome with original string. If the string wasn't split by given delimiter that outcome should be the same.
Eg. like this:
var str = "5+1"
var delimiters = arrayOf("+","-","*","/")
var found = "Not found"
for (delimiter in delimiters) {
var splited = str.split(delimiter)
if(splited[0] != str) {
found = delimiter
break
}
}
println(found)
If I want to use $ sign in multiline strings, how do I escape it?
val condition = """ ... $eq ... """
$eq is parsed as a reference to a variable. How to escape $, so that it will not be recognized as reference to variable? (Kotlin M13)
From the documentation
A raw string is delimited by a triple quote ("""), contains no
escaping and can contain newlines and any other character
You would need to use a standard string with newlines
" ...\n \$eq \n ... "
or you could use the literal representation
""" ... ${'$'}eq ... "
Funny, but that works:
val eq = "\$eq"
print("""... $eq ..."""") // just like you asked :D
Actually, if eq is a number (a price, or sth), then you probably want to calculate it separately, and an additional external calculation as I suggested won't hurt.
In the case where you know ahead of time what $-variables you want (like when querying Mongo, as it looks like you might be doing), you can create a little helper object that defines those variables. You also get some protection against accidentally misspelling one of your operators, which is neat.
object MongoString {
inline operator fun invoke(callback: MongoString.() -> String) = callback()
val eq = "\$eq"
val lt = "\$lt"
// ... and all the other operators ...
}
fun test() {
val query = MongoString { """{"foo": {$lt: 10}}""" }
}
I wrote simple versions for update and query strings for mongo here: https://gist.github.com/Yona-Appletree/29be816ca74a0d93cdf9e6f5e23dda15
The plot
There is a rather complicatedly formatted string, like there's no such readable regex that parses it. And the aim is to get a specific substring for example, and to get it's original position. That substring is reached after parsing a bit, like trimming, removing the beginning something and searching the n-th element for example. I just want to demonstrate you the complexity with this example, otherwise it's pretty general.
For demonstration, see this rudimentary example. The way it is isn't really important, just to reach a pretty complicated parse model. Obviously, there can be more rule and you can write a simplier model as well.
FirstBlock{Index1, Index2} SecondBlock ThirdBlock
{ FirstBlock {Index1,Index2} SecondBlock}
{FirstBlock SecondBlock ThirdBlock FourthBlock}
I've tried to make as random as it could be. The parsing model is like:
string text = "{ FirstBlock {Index1,Index2} SecondBlock}";
text = text.Trim();
if (text.First() == '{')
{
text = text.SubString(1, text.Length - 2);
}
text = text.Trim();
string firstBlock = text.Split(new char[] { ' ', '{' })[0];
text = text.Remove(0, firstBlock.Length).Trim();
string indices = "";
if (text.First() == '{')
{
indices = text.Split(new char[] { '{', '}' })[0];
text = text.Remove(0, indices.Length).Trim();
}
string[] blocks = text.Split(' ');
The easy way
There is a way that is pretty easy to implement and straightforward. But does not give you the correct result sometimes. That way you parse the string and get the substring and then you make a re-search, for example string.IndexOf() and get the position. But if there are two match for example, you are given the first one even though it is not sure you wanted that one.
My notion
The way I think is quite elegant but still not consummate is to index the characters of the string at the beginning, then parse it, and eventually you end up with the proper characters and their position also. My problem there is that then you can't really use the functions the library gives, and I don't know a way to do that. Using the snippet above:
List<Tuple<int, char>> indexedText = text
.Select((ch, index) => new Tuple<int, char>(index, ch))
.ToList();
And with this structure you can still process the string without library methods but you are given the position indices eventually. For example, trim:
indexedText = indexedText
.SkipWhile(indexedChar => char.IsWhiteSpace(indexedChar.Item2))
.ToList();
The actual question
The question can either be a new solution or the way you can use library methods with indexed strings. The aim is to get the indices back after parsing a string. It is possible that there is a very simple way that is just out of my scope but I haven't found a proper solution yet. The solution I don't want is to simplify the parsing system, as I said it is just for demonstration.
I'm starting to like the Swift string formatting since it uses variable names in the string rather than ambiguous formatting tags like "%#"
I want to load a large string from a file that has Swift-style formatting in it (like this)
Now is the time for all good \(who) to come to babble incoherently.
Then I want to feed the contents of that String variable into a statement that lest me replace
\(who)
with the contents of the constant/variable who at runtime.
The code below works with a string constant as the formatting string.
let who = "programmers"
let aString = "Now is the time for all good \(who) to come to babble incoherently."
That code does formatting of a quoted string that appears in-line in my code.
Instead I want something like the code
let formatString = "Now is the time for all good %# to come to babble incoherently."
aString = String(format: formatString, who)
But where I can pass in a Swift-style format string in a constant/variable I read from a file.
Is that possible? I didn't have any luck searching for it since I wasn't exactly sure what search terms to use.
I can always use C-style string formatting and the String class' initWithFormat method if I have to...
I don't think there's a way to do this. String interpolation is implemented via conforming to the StringInterpolationConvertible protocol, and presumably you're hoping to tap into that in the same way you can tap into the methods required by StringLiteralConvertible, a la:
let someString = toString(42)
// this is the method String implements to conform to StringLiteralConvertible
let anotherString = String(stringLiteral: someString)
// anotherString will be "42"
print(anotherString)
Unfortunately, you can't do quite the same trick with StringInterpolationConvertible. Seeing how the protocol works may help:
struct MyString: Printable {
let actualString: String
var description: String { return actualString }
}
extension MyString: StringInterpolationConvertible {
// first, this will get called for each "segment"
init<T>(stringInterpolationSegment expr: T) {
println("Processing segment: " + toString(expr))
actualString = toString(expr)
}
// here is a type-specific override for Int, that coverts
// small numbers into words:
init(stringInterpolationSegment expr: Int) {
if (0..<4).contains(expr) {
println("Embigening \(expr)")
let numbers = ["zeo","one","two","three"]
actualString = numbers[expr]
}
else {
println("Processing segment: " + toString(expr))
actualString = toString(expr)
}
}
// finally, this gets called with an array of all of the
// converted segments
init(stringInterpolation strings: MyString...) {
// strings will be a bunch of MyString objects
actualString = "".join(strings.map { $0.actualString })
}
}
let number = 3
let aString: MyString = "Then shalt thou count to \(number), no more, no less."
println(aString)
// prints "Then shalt thou count to three, no more, no less."
So, while you can call String.init(stringInterpolation:) and String.init(stringInterpolationSegment:) directly yourself if you want (just try String(stringInterpolationSegment: 3.141) and String(stringInterpolation: "blah", "blah")), this doesn't really help you much. What you really need is a facade function that coordinates the calls to them. And unless there's a handy pre-existing function in the standard library that does exactly that which I've missed, I think you're out of luck. I suspect it's built into the compiler.
You could maybe write your own to achieve your goal, but a lot of effort since you'd have to break up the string you want to interpolate manually into bits and handle it yourself, calling the segment init in a loop. Also you'll hit problems with calling the combining function, since you can't splat an array into a variadic function call.
I don't think so. The compiler needs to be able to resolve the interpolated variable at compile time.
I'm not a Swift programmer, specifically, but I think you can workaround it to something pretty close to what you want using a Dictionary and standard string-replacing and splitting methods:
var replacement = [String: String]()
replacement["who"] = "programmers"
Having that, you can try to find the occurrences of "\(", reading what is next and prior to a ")", (this post can help with the split part, this one, with the replacing part), finding it in the dictionary, and reconstructing your string from the pieces you get.
this one works like a charm:
let who = "programmers"
let formatString = "Now is the time for all good %# to come to babble incoherently."
let aString = String(format: formatString, who)