Why the string.Replace is not working in golang - string

I'm making a program to remove the letters from a string if they exsists. But the expected result will not come. The Program I have tried is below:-
package main
import (
"fmt"
"strings"
)
func main() {
strValue := "This is a string"
stringRemove := []string{"a", "an"}
var removalString string
for _, wordToRemove := range stringRemove {
removalString = strings.Replace(strValue, wordToRemove, "", -1)
}
fmt.Println(removalString)
result := strings.Replace(strValue, " ", "", -1)
result1 := strings.ToLower(result)
fmt.Println(result1)
}
Output:-
This is a string
thisisastring
If I use the line fmt.Println(removalString) in the for loop then it will print the result:-
output:-
This is string
This is a string
This is a string
thisisastring
Expected output:-
thisisstring
kheedn li link

You always apply the replace operation on the original string strValue, so after the loop only the last removable word will be removed (which is not even contained in your example). You should store the result of strings.Replace() (you do that), and use this in the next iteration:
removalString := strValue
for _, wordToRemove := range stringRemove {
removalString = strings.Replace(removalString, wordToRemove, "", -1)
}
And also use this in your last replacement:
result := strings.Replace(removalString, " ", "", -1)
result1 := strings.ToLower(result)
Then output will be (try it on the Go Playground):
This is string
thisisstring
Also note that to remove spaces, you can add that to the list of removable words, and you don't need to always create new variables, you can reuse existing ones.
This will also perform the same transformation:
s := "This is a string"
words := []string{"a", "an", " "}
for _, word := range words {
s = strings.Replace(s, word, "", -1)
}
s = strings.ToLower(s)
fmt.Println(s)
Try it on the Go Playground.

this is what youre looking for:
package main
import (
"fmt"
"strings"
)
func main() {
strValue := "This is a string"
stringRemove := []string{"a", "an"}
removalString := strValue
for _, wordToRemove := range stringRemove {
removalString = strings.Replace(removalString, wordToRemove, "", -1)
}
fmt.Println(removalString)
result := strings.Replace(strValue, " ", "", -1)
result1 := strings.ToLower(result)
fmt.Println(result1)
}

removalString will be set new value each loop. So fmt.Println(removalString) will show the result of last loop.
var removalString string
for _, wordToRemove := range stringRemove {
removalString = strings.Replace(strValue, wordToRemove, "", -1)
}
fmt.Println(removalString)
You may do like this
strValue := "This is a string"
stringRemove := []string{"a", "an"}
for _, wordToRemove := range stringRemove {
strValue = strings.Replace(strValue, wordToRemove, "", -1)
}
fmt.Println(strValue)

Related

How to print each elements string with its frequency based on index in map - Golang

Let say I have input and output string where the output will be the frequency of each elements in the string and the char itself
input := "programming"
output := "p2ro2ga2min"
How can I print it based on index after I found the freq of distinct character
This is my code
func countFreq(s string) {
sMap := make(map[string]int)
for _, v := range s {
sMap[string(v)]++
}
for i, v := range sMap {
fmt.Printf("%v%v", i, v)
}
// Don't know what to do next
}
The output of code is
output: n1p1r2o1g2a1m2i1
#icza's answer is great. Here's an alternative that I thought of before but only just got around to writing.
It uses a string to keep track of the rune order but you could use a string builder if speed is important.
func countFreq(s string) {
sMap := make(map[rune]int)
sOut := ""
for _, c := range s {
sMap[c]++
if sMap[c] == 1 {
sOut += string(c)
}
}
for _, c := range sOut {
if sMap[c] > 1 {
fmt.Print(sMap[c])
}
fmt.Printf("%c", c)
}
}
You're counting runes, so use a map of map[rune]int, so you can omit the conversions back to string.
Maps are unordered, so if you want the output in the same order as the input, you can't (shouldn't) iterate over the map.
Once you counted the letters, range over the input letters again, and get the frequency from the map, and remove it. If the count is greater than 1, also print the number.
func countFreq(s string) {
sMap := make(map[rune]int)
for _, v := range s {
sMap[v]++
}
for _, v := range s {
count := sMap[v]
if count == 0 {
continue // Char already printed and removed
}
delete(sMap, v)
if count > 1 {
fmt.Print(count)
}
fmt.Print(string(v))
}
}
Testing it:
for _, s := range []string{"programming", "ab", "aba", "aabcdeac"} {
fmt.Println("In:", s)
fmt.Print("Out: ")
countFreq(s)
fmt.Println()
}
This will output (try it on the Go Playground):
In: programming
Out: p2ro2ga2min
In: ab
Out: ab
In: aba
Out: 2ab
In: aabcdeac
Out: 3ab2cde

Loop through column cells in golang and excelize

I was wondered how to loop over column cells of excel sheet in golang, here is my excel file:
I have tried this piece of code for other reason
package main
import (
"fmt"
"github.com/xuri/excelize/v2"
)
func main() {
f, err := excelize.OpenFile("pricematching.xlsx")
if err != nil {
fmt.Println(err)
return
}
// Get all the rows in the sheet1 section.
rows, err := f.GetCellValue("sheet1", "A2")
fmt.Print(rows, "\t")
}
No matter how's your excel file, this is the way to read each cell:
xlsxFile, error := excelize.OpenFile(filePath)
for _, sheetName := range xlsxFile.GetSheetMap() {
for rowIndex, rowValues := range xlsxFile.GetRows(sheetName) {
for columnIndex, columnValue := range rowValues {
// do what ever you want here
}
}
}
Not sure what exactly you need, but this is a simple way to get all cells in a column (if you know how many rows you want to read):
package main
import (
"fmt"
"github.com/xuri/excelize/v2"
)
func main() {
f, err := excelize.OpenFile("pricematching.xlsx")
if err != nil {
fmt.Println(err)
return
}
columnName := "A"
sheetName := "sheet1"
totalNumberOfRows := 20
for i := 1; i < totalNumberOfRows; i++ {
cellName := fmt.Sprintf("%s%d", columnName, i)
// fmt.Println(cellName)
cellValue, err := f.GetCellValue(sheetName, cellName)
fmt.Printf("%s\t", cellValue)
}
}

How to pass []string or []byte type to SplitAfterN in golang?

I'm reading file line by line and like to split line based on substring. But when I use SplitAfterN with read line passed, I'm facing below error,
cannot convert 'variable' (type []string) to type string
where 'variable' = []string type
package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
"strings"
)
func main() {
var fLine []string
FileName := flag.String("fpath", "Default file path", "File path description ")
flag.Parse()
fptr, err := os.Open(*FileName)
if err != nil {
log.Fatal(err)
}
FileScanner := bufio.NewScanner(fptr)
for FileScanner.Scan() {
// Append each line into one buffer while reading
fLine = append(fLine, FileScanner.Text())
splitline := strings.SplitAfterN(fLine, "12345", 2)
fmt.Println("Splited string = ", splitline[1])
}
}
I'm expecting below line to split passed argument (fLine)
splitline := strings.SplitAfterN(fread, "12345", 2)
The (last) line you read is not fLine, that is a slice of all lines. The last line is returned by FileScanner.Text(). If you want to split the last line, either store that in a variable, or use the last element of the slice.
If you choose to store it in a variable:
line := FileScanner.Text()
fLine = append(fLine, line)
splitline := strings.SplitAfterN(line, "12345", 2)
If you just want to use the last slice element:
fLine = append(fLine, FileScanner.Text())
splitline := strings.SplitAfterN(fLine[len(fLine)-1], "12345", 2)
So you just want to convert the slice to a string, right?
This should do what you need..
So:
splitline := strings.SplitAfterN(strings.Join(fLine," "), "12345", 2)

Expand a string of slice by delimiter

I want to expand a string of slice by delimiter "/".
For example, expanding the following slice
s := []string{"5/3","9","5/4/1","6"}
Should produce individual slices :
["5","9","5","6"] ["5","9","4","6"] ["5","9","1","6"]
["3","9","5","6"] ["3","9","4","6"] ["3","9","1","6"]
I am pretty much stuck here
var c [][]string{}
s := []string{"5/3","9","5/4/1","6"}
for _, v := range s {
combos := strings.Split(v, "/")
for _, combo := range combos {
}
}
Running time aside, you can achieve this with recursion.
func Perm(digits [][]string) (perm [][]string) {
if len(digits) == 0 || len(digits) == 1 {
return digits
}
nextDigits := Perm(digits[1:])
for _, digit := range digits[0] {
for _, next := range nextDigits {
cat := append([]string{digit}, next...)
perm = append(perm, cat)
}
}
return perm
}
Playground

Finding longest word in golang

Trying to find the longest word using Go from a sentence.
At the moment I am using this method:
func longestWord(s string) string {
newArr := strings.Split(s, " ")
l := len(newArr[0])
long := newArr[0]
var result string
// fmt.Println(long)
for _, lenString := range newArr {
if len(lenString) > l {
// ll := len(lenString)
// l := len(lenString)
d := &l
p := &long
c := &result
*d = len(lenString)
*p = lenString
*c = lenString
// fmt.Println(lenString)
} else {
c := &result
*c = newArr[0]
}
}
return result
}
func main() {
args := "Monday Tuesday Friday Sunday Wednesday"
fmt.Println(longestWord(args))
}
But I'm not sure that this is the best method to achieve that. Is there any other elegant way to do that? I know that there is one more method by using sort, but I would prefer more using the way with iteration between words.
"Best" solution
We can even write it more compact than the other answers by taking advantage of the following:
using tuple assignments
initializing the best and its length with the zero values ("" and 0) and omitting the check for 0 words as the for range handles that properly
no need to store words as a local variable as it is only used in the loop
We lose nothing from readability:
func longestWord(s string) string {
best, length := "", 0
for _, word := range strings.Split(s, " ") {
if len(word) > length {
best, length = word, len(word)
}
}
return best
}
Testing it:
fmt.Printf("%q\n", longestWord(""))
args := "Monday Tuesday Friday Sunday Wednesday"
fmt.Printf("%q\n", longestWord(args))
Output (try it on the Go Playground):
""
"Wednesday"
Most compact solution
Note that storing the length of the best is optional and is purely for optimization purposes, since if we have best, its length is always len(best).
Taking advantage of this, and that we can use named result parameters (and that all variables are initialized to the zero value of their types unless an initial value is provided–which for string is ""), we can even write it more compact, again losing nothing from readability:
func longestWord(s string) (best string) {
for _, word := range strings.Split(s, " ") {
if len(word) > len(best) {
best = word
}
}
return
}
Testing and output is the same, try it on the Go Playground. Again, in most cases this is probably slightly slower compared to when we stored the length too.
That totally works! You could make it a bit shorter, while also using longer variable names that explain a bit more about your intention.
func longestWord(s string) string {
words := strings.Split(s, " ")
if len(words) == 0 {
return ""
}
best := words[0]
best_length := 0
for _, word := range words {
if len(word) > best_length {
best = word
best_length = len(word)
}
}
return best
}
You could change this to track a pointer instead of the word itself if you like.
I would do it like this:
func longestWord(s string) string {
newArr := strings.Split(s, " ")
longestWord := ""
longestLength := 0
// loop through the array
for _, word := range newArr {
// save length of word in the actual iteration
length := len(word)
// if length is larger, than longest
if length > longestLength {
// save the new longest word
longestWord = word
longestLength = length
}
}
// return the longest word
return longestWord
}
Implementation can be found on the go playground

Resources