Loop repeated data ini a string with Golang - go

I have a string like this
xx5645645yyxx9879869yyxx3879870977yy
Want to get result like following with loop
xx5645645yy
xx9879869yy
xx3879870977yy
I have no idea to do it, any kind of help is greatly appreciated, thanks

You can use the strings.Split() function and split on "xx", then prepend "xx" back to each of the split substrings in the loop:
package main
import (
"fmt"
"strings"
)
func main() {
s := "xx5645645yyxx9879869yyxx3879870977yy"
items := strings.Split(s, "xx")[1:] // [1:] to skip the first, empty, item
for _, item := range items {
fmt.Println("xx" + item)
}
}
Which produces:
xx5645645yy
xx9879869yy
xx3879870977yy

Related

How to parse email addresses from a long string in Golang

How can I extract only email addresses from a long string in Golang? For example:
"a bunch of irrelevant text fjewiwofjfjvnvkdlslsosiejwoqlwpwpwo
mail=jim.halpert#gmail.com,ou=f,c=US
mail=apple.pie#gmail.com,ou=f,c=US
mail=hello.world#gmail.com,ou=f,c=US
mail=alex.alex#gmail.com,ou=f,c=US
mail=bob.jim#gmail.com,ou=people,ou=f,c=US
mail=arnold.schwarzenegger#gmail.com,ou=f,c=US"
This would return a list of all the emails:
[jim.halpert#gmail.com, apple.pie#gmail.com, etc...]
Each email address would begin with "mail=" and end with a comma ",".
For this you need to breakdown the long go string into parts that you need. You can do filtration and searching using Regular Expressions to match the email pattern you see above.
Here's a piece of code using Regular Expressions to first obtain the section with "mail=" then further format the email removing the trailing ,
import (
"fmt"
"regexp"
"strings"
)
func main() {
var re = regexp.MustCompile(`(?m)mail=[A-Za-z.#0-9]+\,`)
var str = `a bunch of irrelevant text fjewiwofjfjvnvkdlslsosiejwoqlwpwpwo
mail=jim.halpert#gmail.com,ou=f,c=US
mail=apple.pie#gmail.com,ou=f,c=US
mail=hello.world#gmail.com,ou=f,c=US
mail=alex.alex#gmail.com,ou=f,c=US
mail=bob.jim#gmail.com,ou=people,ou=f,c=US
mail=arnold.schwarzenegger#gmail.com,ou=f,c=US`
for i, match := range re.FindAllString(str, -1) {
fmt.Println(match, "found at index", i)
email := strings.Split(match, "=")[1]
email = strings.ReplaceAll(email, ",", "")
fmt.Print(email)
}
}
while i agree with the comment from user datenwolf here is another version which does not involve regular expressions.
It also handle more complex emails format including comma within the local parts. Something uneasy to implement using regexp.
see https://stackoverflow.com/a/2049510/11892070
import (
"bufio"
"fmt"
"strings"
)
var str = `a bunch of irrelevant text fjewiwofjfjvnvkdlslsosiejwoqlwpwpwo
mail=jim.halpert#gmail.com,ou=f,c=US
mail=apple.pie#gmail.com,ou=f,c=US
mail=hello.world#gmail.com,ou=f,c=US
mail=alex.alex#gmail.com,ou=f,c=US
mail=bob.jim#gmail.com,ou=people,ou=f,c=US
mail=arnold.schwarzenegger#gmail.com,ou=f,c=US
mail=(comented)arnold.schwarzenegger#gmail.com,ou=f,c=US
mail="(with comma inside)arnold,schwarzenegger#gmail.com",ou=f,c=US
mail=nocommaatall#gmail.com`
func main() {
var emails []string
sc := bufio.NewScanner(strings.NewReader(str))
for sc.Scan() {
t := sc.Text()
if !strings.HasPrefix(t, "mail=") {
continue
}
t = t[5:]
// Lookup for the next comma after the #.
at := strings.Index(t, "#")
comma := strings.Index(t[at:], ",")
if comma < 0 {
email := strings.TrimSpace(t)
emails = append(emails, email)
continue
}
comma += at
email := strings.TrimSpace(t[:comma])
emails = append(emails, email)
}
for _, e := range emails {
fmt.Println(e)
}
}
You can use this package to do that :
https://github.com/hamidteimouri/htutils/blob/main/htregex/htregex.go
// Emails finds all email strings
func Emails(text string) []string {
return match(text, EmailsRegex)
}
you can use an original package from golang is regexp.Compile or regexp.MustCompile
r, _ := regexp.Compile(regexEmail)
newVariable := `a bunch of irrelevant text fjewiwofjfjvnvkdlslsosiejwoqlwpwpwo
mail=jim.halpert#gmail.com,ou=f,c=US
mail=apple.pie#gmail.com,ou=f,c=US
mail=hello.world#gmail.com,ou=f,c=US
mail=alex.alex#gmail.com,ou=f,c=US
mail=bob.jim#gmail.com,ou=people,ou=f,c=US
mail=arnold.schwarzenegger#gmail.com,ou=f,c=US`
fmt.Printf("%#v\n", r.FindStringSubmatch(newVariable))
fmt.Printf("%#v\n", r.SubexpNames())

How to delete an element from a slice that's inside a map?

I have a a map which has a key and multiple values for that key.
What i want to do is delete a single value from values.
Example:
map1 := make(map[string][]string)
str1 := []string{"Jon", "Doe", "Captain", "America"}
str2 := "Doe"
map1["p1"] = str1
In the above example I want to remove value form the "p1" if it is present in str2, in my case it is "Doe"
after removing the value map should be like this
p1:[Jon Captain America]
Is this possible or do i have to rewrite the whole map again?
It's not possible to "in place" delete an element from a slice that's inside a map. You need to first get the slice from the map, delete the element from the slice, and then store the result of that in the map.
For finding the element's index by its value and then deleting it from the slice you can use the golang.org/x/exp/slices package if you are using Go1.18.
package main
import (
"fmt"
"golang.org/x/exp/slices"
)
func main() {
map1 := make(map[string][]string)
str1 := []string{"Jon", "Doe", "Captain", "America"}
str2 := "Doe"
map1["p1"] = str1
idx := slices.Index(map1["p1"], str2)
map1["p1"] = slices.Delete(map1["p1"], idx, idx+1)
fmt.Println(map1)
}
https://go.dev/play/p/EDTGAJT-VdM
package main
func main () {
var sessions = map[string] chan int{};
delete(sessions, "moo");
}
or
package main
func main () {
var sessions = map[string] chan int{};
sessions["moo"] = make (chan int);
_, ok := sessions["moo"];
if ok {
delete(sessions, "moo");
}
}

How can I trim whitespaces in Go from a slice after Split

I have a string that is comma separated, so it could be
test1, test2, test3 or test1,test2,test3 or test1, test2, test3.
I split this in Go currently with strings.Split(s, ","), but now I have a []string that can contain elements with an arbitrary numbers of whitespaces.
How can I easily trim them off? What is best practice here?
This is my current code
var property= os.Getenv(env.templateDirectories)
if property != "" {
var dirs = strings.Split(property, ",")
for index,ele := range dirs {
dirs[index] = strings.TrimSpace(ele)
}
return dirs
}
I come from Java and assumed that there is a map/reduce etc functionality in Go also, therefore the question.
You can use strings.TrimSpace in a loop. If you want to preserve order too, the indexes can be used rather than values as the loop parameters:
Go Playground Example
EDIT: To see the code without the click:
package main
import (
"fmt"
"strings"
)
func main() {
input := "test1, test2, test3"
slc := strings.Split(input , ",")
for i := range slc {
slc[i] = strings.TrimSpace(slc[i])
}
fmt.Println(slc)
}
Easy way without looping
test := "2 , 123, 1"
result := strings.Split(strings.ReplaceAll(test," ","") , ",")
The encoding/csv package can handle this:
package main
import (
"encoding/csv"
"fmt"
"strings"
)
func main() {
for _, each := range []string{
"test1, test2, test3", "test1, test2, test3", "test1,test2,test3",
} {
r := csv.NewReader(strings.NewReader(each))
r.TrimLeadingSpace = true
s, e := r.Read()
if e != nil {
panic(e)
}
fmt.Printf("%q\n", s)
}
}
https://golang.org/pkg/encoding/csv#Reader.TrimLeadingSpace
If you already use regexp may be you can split using regular expressions:
regexp.MustCompile(`\s*,\s*`).Split(test, -1)
This solution is probably slower than the standard Split + TrimSpaces, but is more flexible. For example if you want to skip empty fields you can :
regexp.MustCompile(`(\s*,\s*)+`).Split(test, -1)
or to use multiple separators
regexp.MustCompile(`\s*[,;]\s*`).Split(test, -1)
You can test it in the go playground.

Go, not getting string value

package main
import (
"fmt"
"io/ioutil"
)
func main() {
// Just count the files...
systems,_ := ioutil.ReadDir("./XML")
fmt.Printf("# of planetary systems\t%d\r\n", len(systems))
// For each datafile
for _,element := range systems {
fmt.Println(element.Name)
}
}
This line...
fmt.Println(element.Name)
Is outputting a memory address instead of what I assume to be the filename string. Why? How do I get the actual string? Thanks.
Also all the addresses are the same, I would expect them to difer, meaning my for-each loop might be broken.
FileInfo.Name is a function of the FileInfo interface; the function's memory address is being printed. To display the name of the file, you need to evaluate the function before printing:
for _, element := range systems {
fmt.Println(element.Name())
}

How to return the unique elements of large data structures in go?

I am new to Go language and troubling in the code to find the unique elements in the go.
var arr [10]string
arr[0]="table"
arr[1]="chair"
arr[2]="table"
arr[3]="table"
arr[4]="chair"
arr[5]="bench"
arr[6]="table,chair"
arr[7]="bench,chair"
arr[8]="chair,table,bench"
arr[9]="car"
The output should be like:
table
chair
bench
car
I am really stuck on this. how to get the unique elements from the above array.
The array contains comma seperated values also but i need to print only the unique elements.
Pls someone help me on this.
Thanks for advance.
Idea: use map[string]bool to collect unique elements, use strings.Split to split comma-separated list of words into strings.
Example: http://play.golang.org/p/sBopFGrzbX
package main
import (
"fmt"
"strings"
)
func main() {
arr := [...]string{
"table",
"chair",
"table",
"table",
"chair",
"bench",
"table,chair",
"bench,chair",
"chair,table,bench",
"car",
}
m := make(map[string]bool)
for _, e := range arr {
for _, w := range strings.Split(e, ",") {
m[w] = true
}
}
for k, _ := range m {
fmt.Println(k)
}
}

Resources