How to write the result of a function in a slice - string

In the example, everything works fine. But they do not use the variable a and immediately display it https://play.golang.org/p/O0XwtQJRej
But I have a problem:
package main
import (
"fmt"
"strings"
)
func main() {
str := "fulltext"
var slice []string
slice = strings.Split(str , "")
fmt.Printf("anwer: ", slice)
}
Whence in the answer there are superfluous characters, for example
%! (EXTRA [] string =
P.S. I know that I need to use append to add elements to the slice, but now I do not understand how to apply append here.
UP:
Now I have the answer:
anwer: %!(EXTRA []string=[f u l l t e x t])
But I need just:
[f u l l t e x t]
But I do not understand how I should change my code?

The problem is not with the assignment of the return value of strings.Split() to the local variable slice, which is totally fine.
The problem is that you used fmt.Printf() which expects a format string, and based on that format string it formats / substitutes expected parameters. Since your format string does not contain any verbs, that fmt.Printf() call expects no parameters, yet you pass it one, so it signals this with those extra characters (kind of error string).
Provide a valid format string where you indicate you will supply 1 parameter, a slice:
fmt.Printf("answer: %v", slice)
With this, the output is:
answer: [f u l l t e x t]
Or alternatively use fmt.Println(), which does not expect a format string:
fmt.Println("answer:", slice)
(Note that there is no space after the colon, as fmt.Println() adds a space between 2 values if one of them is of type string).
Output is the same. Try the examples on the Go Playground.
Staying with fmt.Printf(), when the parameter involves string values, the %q verb is often more useful, as that will print quoted string values, much easier to spot certain mistakes (e.g. invisible characters, or if a string contains spaces, it will become obvious):
fmt.Printf("answer: %q\n", slice)
Output of this (try it on the Go Playground):
answer: ["f" "u" "l" "l" "t" "e" "x" "t"]
If you'd wanted to append the result of a function call, this is how it could look like:
slice := []string{"initial", "content"}
slice = append(slice, strings.Split(str, "")...)
fmt.Printf("answer: %q\n", slice)
And now the output (try it on the Go Playground):
answer: ["initial" "content" "f" "u" "l" "l" "t" "e" "x" "t"]

Give to printf the expected format, in most cases, %v is fine.
package main
import (
"fmt"
"strings"
)
func main() {
str := "fulltext"
var slice []string
slice = strings.Split(str, "")
fmt.Printf("anwer: %v", slice)
}
see https://golang.org/pkg/fmt/ for more info.

Related

Replace a character in a string in golang

I am trying to replace a specific position character from an array of strings. Here is what my code looks like:
package main
import (
"fmt"
)
func main() {
str := []string{"test","testing"}
str[0][2] = 'y'
fmt.Println(str)
}
Now, running this gives me the error:
cannot assign to str[0][2]
Any idea how to do this? I have tried using strings.Replace, but AFAIK it will replace all the occurrence of the given character, while I want to replace that specific character. Any help is appreciated. TIA.
Strings in Go are immutable, you can't change their content. To change the value of a string variable, you have to assign a new string value.
An easy way is to first convert the string to a byte or rune slice, do the change and convert back:
s := []byte(str[0])
s[2] = 'y'
str[0] = string(s)
fmt.Println(str)
This will output (try it on the Go Playground):
[teyt testing]
Note: I converted the string to byte slice, because this is what happens when you index a string: it indexes its bytes. A string stores the UTF-8 byte sequence of the text, which may not necessarily map bytes to characters one-to-one.
If you need to replace the 2nd character, use []rune instead:
s := []rune(str[0])
s[2] = 'y'
str[0] = string(s)
fmt.Println(str)
In this example it doesn't matter though, but in general it may.
Also note that strings.Replace() does not (necessarily) replace all occurrences:
func Replace(s, old, new string, n int) string
The parameter n tells how many replacement are to be performed max. So the following also works (try it on the Go Playground):
str[0] = strings.Replace(str[0], "s", "y", 1)
Yet another solution could be to slice the string up until the replacable character, and starting from the character after the replacable one, and just concatenate them (try this one on the Go Playground):
str[0] = str[0][:2] + "y" + str[0][3:]
Care must be taken here too: the slice indices are byte indices, not character (rune) indices.
See related question: Immutable string and pointer address
Here's a function that will do that for you. It takes care of converting the string that you want to modify into a []rune, and then back out to string.
If your intention is to replace bytes rather than runes, you can:
copy this function's code, rename it from runeSub to byteSub
change the r rune parameter to b byte
Also available on repl.it
package main
import "fmt"
// runeSub - given an array of strings (ss), replace the
// (ri)th rune (character) in the (si)th string
// of (ss), with the rune (r)
//
// ss - the array of strings
// si - the index of the string in ss that you want to modify
// ri - the index of the rune in ss[si] that you want to replace
// r - the rune you want to insert
//
// NOTE: this function has no panic protection from things like
// out-of-bound index values
func runeSub(ss []string, si, ri int, r rune) {
rr := []rune(ss[si])
rr[ri] = r
ss[si] = string(rr)
}
func main() {
ss := []string{"test","testing"}
runeSub(ss, 0, 2, 'y')
fmt.Println(ss)
}

How to print float number where decimal point is comma (,) in fmt.Sprintf

I am printing floating point value(eg: 52.12) like this:
fmt.Sprintf("%.2f%s", percentageValue, "%%")
Output is like 52.12%. But I want to print it in other language than English where decimal point is comma ,. How to do it in Go using fmt.Sprintf. I want output like this 52,12% .
The fmt package does not support the functionality to replace the delimiter in a floating point number. You should instead use the golang.org/x/text/message package, which is designed for this purpose.
The standard lib (and the fmt package) does not support localized text and number formatting.
If you only need to localize the decimal point, you may use the easy way to simply replace the dot (.) with the comma character (,) like this:
percentageValue := 52.12
s := fmt.Sprintf("%.2f%%", percentageValue)
s = strings.Replace(s, ".", ",", -1)
fmt.Println(s)
(Also note that you may output a percent sign % by using 2 percent signs %% in the format string.)
Which outputs (try it on the Go Playground):
52,12%
Or with a mapping function:
func dot2comma(r rune) rune {
if r == '.' {
return ','
}
return r
}
func main() {
percentageValue := 52.12
s := fmt.Sprintf("%.2f%%", percentageValue)
s = strings.Map(dot2comma, s)
fmt.Println(s)
}
Output is the same. Try this one on the Go Playground.
Yet another solution could be to format the integer and fraction part separately, and glue them together with a comma , sign:
percentageValue := 52.12
i, f := math.Modf(percentageValue)
s := fmt.Sprint(i) + "," + fmt.Sprintf("%.2f%%", f)[2:]
fmt.Println(s)
Try this one on the Go Playground.
Note that this latter solution needs "adjusting" if the percent value is negative:
percentageValue := -52.12
i, f := math.Modf(percentageValue)
if f < 0 {
f = -f
}
s := fmt.Sprint(i) + "," + fmt.Sprintf("%.2f%%", f)[2:]
fmt.Println(s)
This modified version will now print -52,12% properly. Try it on the Go Playground.
If you need "full" localization support, then do check out and use golang.org/x/text/message, which "implements formatted I/O for localized strings with functions analogous to the fmt's print functions. It is a drop-in replacement for fmt."
I found a library to do that, it's called humanize.
With this you can do something like this fmt.Println(humanize.FormatFloat("00,00", 52.20))
See in the link below the instructions:
https://github.com/dustin/go-humanize
I have solved the problem by this:
func getFormattedValue(percentageValue float64) string{
value := fmt.Sprintf("%.2f%s", percentageValue, "%")
return strings.Replace(value, ".", ",", -1)
}
I am taking float value and converting to string then replacing . with ,

golang convert "type []string" to string

I see some people create a for loop and run through the slice as to create a string, is there an easier way to convert a []string to a string?
Will sprintf do it?
You can use strings.Join(arr \[\]string, separator string) string.
This is a simple example, which you can paste into the main function:
stringArray := []string {"Hello","world","!"}
justString := strings.Join(stringArray," ")
fmt.Println(justString)
And link to working example on playground.
Or using very simple function
simple function
Will Sprint do it?
Yes indeed!
Here is another way to convert to a string if all you care about is that it is a string and not specifically how it looks (see answers above with strings.Join for a little more flexibility).
The advantage of this method (or variations such as Sprintf), is it will work with (almost) every other data such as maps and structs and any custom type that implements the fmt.Stringer inteface.
stringArray := []string {"Hello","world","!"}
justString := fmt.Sprint(stringArray)
Here is a link to a working example.
It can be done easily using Join function by importing strings package. You need to pass the slice of strings and the separator you need to separate the elements in the string. (examples: space or comma)
func Join(elems []string, sep string) string
Example Code :
package main
import (
"fmt"
"strings"
)
func main() {
sliceStr := []string{"a","b","c","d"}
str := strings.Join(sliceStr,", ")
fmt.Println(str)
}
//output: a, b, c, d
If you don't care about the separator, you can use path:
package main
import "path"
func main() {
a := []string{"south", "north"}
s := path.Join(a...)
println(s == "south/north")
}
https://golang.org/pkg/path#Join
package main
import (
"fmt"
"reflect"
"strings"
)
func main() {
str1 := []string{"Trump", "In", "India", "On", "Feb 25"}
fmt.Println(str1)
fmt.Println(reflect.TypeOf(str1))
str2 := strings.Join(str1, " ")
fmt.Println(str2)
fmt.Println(reflect.TypeOf(str2))
str3 := strings.Join(str1, ", ")
fmt.Println(str3)
fmt.Println(reflect.TypeOf(str3))
}
Below is the ouput of the above program :-
go run hello.go
[Trump In India On Feb 25]
[]string
Trump In India On Feb 25
string
Trump, In, India, On, Feb 25
string
In the above code, first, we have defined a slice of string and then use the reflect package to determine the datatype of the slice.
We have imported the “strings” module. With strings.Join() method, and we combine all elements of a string slice into a string. So, Golang string.Join() function that converts slice to string. We have passed the space(” “) as a delimiter. So we will join the slice elements by space.
The second argument to strings.Join() is the delimiter. For no delimiter, please use an empty string literal.
In the next step, we have again used the TypeOf() function to check the data type.
Then we have used the Golang string.Join() function again, but this time, we have passed (,) Comma. So, command separated values will be returned, which is also a type of string.
So, if you want to get CSV values in Golang, then you can use the Go string.Join() method.
You can also try with functions:-
// abc.go
package main
type deck []string
func (cards deck) toString() string {
// converts slice to string
return strings.Join([]string(cards), ",")
}
//main.go
package main
import "fmt"
func main() {
cards := []string {"Trump", "In", "India", "On", "Feb 25"}
fmt.Println(cards.toString())
}

Indexing string as chars

The elements of strings have type byte and may be accessed using the
usual indexing operations.
How can I get element of string as char ?
"some"[1] -> "o"
The simplest solution is to convert it to an array of runes :
var runes = []rune("someString")
Note that when you iterate on a string, you don't need the conversion. See this example from Effective Go :
for pos, char := range "日本語" {
fmt.Printf("character %c starts at byte position %d\n", char, pos)
}
This prints
character 日 starts at byte position 0
character 本 starts at byte position 3
character 語 starts at byte position 6
Go strings are usually, but not necessarily, UTF-8 encoded. In the case they are Unicode strings, the term "char[acter]" is pretty complex and there is no generall/unique bijection of runes (code points) and Unicode characters.
Anyway one can easily work with code points (runes) in a slice and use indexes into it using a conversion:
package main
import "fmt"
func main() {
utf8 := "Hello, 世界"
runes := []rune(utf8)
fmt.Printf("utf8:% 02x\nrunes: %#v\n", []byte(utf8), runes)
}
Also here: http://play.golang.org/p/qWVSA-n93o
Note: Often the desire to access Unicode "characters" by index is a design mistake. Most of textual data is processed sequentially.
Another option is the package utf8string:
package main
import "golang.org/x/exp/utf8string"
func main() {
s := utf8string.NewString("🧡💛💚💙💜")
t := s.At(2)
println(t == '💚')
}
https://pkg.go.dev/golang.org/x/exp/utf8string

How to split strings into characters in Scala

For example, there is a string val s = "Test". How do you separate it into t, e, s, t?
Do you need characters?
"Test".toList // Makes a list of characters
"Test".toArray // Makes an array of characters
Do you need bytes?
"Test".getBytes // Java provides this
Do you need strings?
"Test".map(_.toString) // Vector of strings
"Test".sliding(1).toList // List of strings
"Test".sliding(1).toArray // Array of strings
Do you need UTF-32 code points? Okay, that's a tougher one.
def UTF32point(s: String, idx: Int = 0, found: List[Int] = Nil): List[Int] = {
if (idx >= s.length) found.reverse
else {
val point = s.codePointAt(idx)
UTF32point(s, idx + java.lang.Character.charCount(point), point :: found)
}
}
UTF32point("Test")
You can use toList as follows:
scala> s.toList
res1: List[Char] = List(T, e, s, t)
If you want an array, you can use toArray
scala> s.toArray
res2: Array[Char] = Array(T, e, s, t)
Actually you don't need to do anything special. There is already implicit conversion in Predef to WrappedString and WrappedString extends IndexedSeq[Char] so you have all goodies that available in it, like:
"Test" foreach println
"Test" map (_ + "!")
Edit
Predef has augmentString conversion that has higher priority than wrapString in LowPriorityImplicits. So String end up being StringLike[String], that is also Seq of chars.
Additionally, it should be noted that if what you actually want isn't an actual list object, but simply to do something which each character, then Strings can be used as iterable collections of characters in Scala
for(ch<-"Test") println("_" + ch + "_") //prints each letter on a different line, surrounded by underscores

Resources