Not being able to concat slices - go

I have the following code, which is returning 4 slices, and I'd like to make it one.
var postArray []string
if strings.Contains(s.Text(), "k") || greaterThan(voteValue) {
postArray = append(postArray, s.Text())
}
for _, p := range postArray {
postArray = append(postArray, p...)
fmt.Println(reflect.TypeOf(p))
}
fmt.Println(postArray)
I'm not posting the whole code because I guess that it won't be needed, the slices returned are these ones:
[31.8k], [3151], [50.5k], [8111], but I'd like to get [31.8k 3151 50.5k 8111]. The p variable is a string, so I get the following error:
cannot use p (type string) as type []string in append
I've tried some things but didn't suceed, hope someone can point me what I'm doing wrong. Thanks in advance!

clearly the way you are appending in your loop will not result in the kinda list you want.
postArray = append(postArray, p...) // you are appending a vector here which you don't want in your case
instead use this,
postArray = append(postArray, p)

Related

Golang fill slice in function not working

I am trying to add stuff to my slice but somehow the slice is never updated.
endpointsList := make([]string, 3)
for _, route := range routes {
if len(route.Endpoints) > 0 {
waitGroup.Add(1)
go endpointRoutine(route, template, route.Protected, &waitGroup, &endpointsList)
}
}
I pass the endpointsList by reference, meaning I should be able to assign new things to its memory location I think.
In the function endpointRoutine I do this:
list := make([]string, 3)
for _, r := range route.Endpoints {
list = append(list, "some data comes here...")
}
endpointsList = &list
When I do a printr after this (below my first bit of code and AFTER the waitGroup.Wait() part) the slice is still empty.
Obviously, I am overwriting the slice now and my final goal is to ADD to the slice. But when I try to add with this code:
endpointsList = append(endpointsList, "fdssdfsdfsdf")
It gives me the error:
cannot use endpointsList (type *[]string) as []Type
Can someone please explain to me what might be wrong?
With endpointsList = &list, you are assigning the pointer pointing to the slice to some other slice. To set the slice, do this instead:
*endpointsList=list

Go: append directly to slice found in a map

I wanted to create a map of slices where values are appended to the corresponding slice. However, when trying to append directly to the slice returned by accessing it (see comment below), it would not be stored, so I had to go with the long form access (line below the comment).
Why is it so? I expected the access to the map to return some sort of pointer, so in my mind mappedAminoAcid == aminoAcidsToCodons[aminoAcid]; clearly, I'm wrong.
Thanks!
aminoAcidsToCodons := map[rune][]string{}
for codon, aminoAcid := range utils.CodonsToAminoAcid {
mappedAminoAcid, ok := aminoAcidsToCodons[aminoAcid]
if ok {
// NOT WORKING: mappedAminoAcid = append(mappedAminoAcid, codon)
aminoAcidsToCodons[aminoAcid] = append(mappedAminoAcid, codon)
} else {
aminoAcidsToCodons[aminoAcid] = []string{codon}
}
}
append returns a new slice if the underlying array has to grow to accomodate the new element. So yes, you have to put the new slice back into the map. This is no different from how strings work, for instance:
var x map[string]string
x["a"] = "foo"
y := x["a"]
y = "bar"
// x["a"] is still "foo"
Since a nil slice is a perfectly fine first argument for append, you can simplify your code to:
aminoAcidsToCodons := map[rune][]string{}
for codon, aminoAcid := range utils.CodonsToAminoAcid {
aminoAcidsToCodons[aminoAcid] = append(aminoAcidsToCodons[aminoAcid], codon)
}

Fill an object in Golang

How can I fill the todos-Object with a for-loop?
type Row struct {
Name string
Completed bool
Due time.Time
Rcount string
}
type Rows []Row
todos := Rows{
Row{Name: "Write presentation"},
Row{Name: "Host meetup"},
}
The question is a little hard to follow but try starting out with something following this pattern (error handling omitted for brevity):
rows, _ := db.Query(string, args...)
var Rows []Row
for rows.Next() {
var r Row
rows.Scan(&r.Name, &r.Completed, &r.Due, &r.Rcount)
Rows = append(Rows, r)
}
If you can clarify the question perhaps we can provide better answers
I think you are looking for the builtin function append
Note that it is normally used in combination with an assignment, because it may have to allocate additional memory. A zero value slice works just fine, no need to call make.
steps := []string{"write program", "???", "profit"}
var rows []Row
for _, tasks := range steps {
rows = append(rows, Row{Name: tasks})
}
If you want to loop over a sqlite3 query result, your loop will look different, but the x = append(x, ...) pattern will stay the same
If you know in advance how big your slice is going to be, explicit initialization with make will be more efficient.
var rows = make([]Row, len(steps))
for i, tasks := range steps {
rows[i] = Row{Name: tasks}
}

List of Strings - golang

I'm trying to make a list of Strings in golang. I'm looking up the package container/list but I don't know how to put in a string. I tried several times, but 0 result.
Should I use another thing instead of lists?
Thanks in advance.
edit: Don't know why are you rating this question with negatives votes...
Modifying the exact example you linked, and changing the ints to strings works for me:
package main
import (
"container/list"
"fmt"
)
func main() {
// Create a new list and put some numbers in it.
l := list.New()
e4 := l.PushBack("4")
e1 := l.PushFront("1")
l.InsertBefore("3", e4)
l.InsertAfter("2", e1)
// Iterate through list and print its contents.
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
}
If you take a look at the source code to the package you linked, it seems that the List type holds a list of Elements. Looking at Element you'll see that it has one exported field called Value which is an interface{} type, meaning it could be literally anything: string, int, float64, io.Reader, etc.
To answer your second question, you'll see that List has a method called Remove(e *Element). You can use it like this:
fmt.Println(l.Len()) // prints: 4
// Iterate through list and print its contents.
for e := l.Front(); e != nil; e = e.Next() {
if e.Value == "4" {
l.Remove(e) // remove "4"
} else {
fmt.Println(e.Value)
}
}
fmt.Println(l.Len()) // prints: 3
By and large, Golang documentation is usually pretty solid, so you should always check there first.
https://golang.org/pkg/container/list/#Element

Can we write a generic array/slice deduplication in go?

Is there a way to write a generic array/slice deduplication in go, for []int we can have something like (from http://rosettacode.org/wiki/Remove_duplicate_elements#Go ):
func uniq(list []int) []int {
unique_set := make(map[int] bool, len(list))
for _, x := range list {
unique_set[x] = true
}
result := make([]int, len(unique_set))
i := 0
for x := range unique_set {
result[i] = x
i++
}
return result
}
But is there a way to extend it to support any array? with a signature like:
func deduplicate(a []interface{}) []interface{}
I know that you can write that function with that signature, but then you can't actually use it on []int, you need to create a []interface{} put everything from the []int into it, pass it to the function then get it back and put it into a []interface{} and go through this new array and put everything in a new []int.
My question is, is there a better way to do this?
While VonC's answer probably does the closest to what you really want, the only real way to do it in native Go without gen is to define an interface
type IDList interface {
// Returns the id of the element at i
ID(i int) int
// Returns the element
// with the given id
GetByID(id int) interface{}
Len() int
// Adds the element to the list
Insert(interface{})
}
// Puts the deduplicated list in dst
func Deduplicate(dst, list IDList) {
intList := make([]int, list.Len())
for i := range intList {
intList[i] = list.ID(i)
}
uniques := uniq(intList)
for _,el := range uniques {
dst.Insert(list.GetByID(el))
}
}
Where uniq is the function from your OP.
This is just one possible example, and there are probably much better ones, but in general mapping each element to a unique "==able" ID and either constructing a new list or culling based on the deduplication of the IDs is probably the most intuitive way.
An alternate solution is to take in an []IDer where the IDer interface is just ID() int. However, that means that user code has to create the []IDer list and copy all the elements into that list, which is a bit ugly. It's cleaner for the user to wrap the list as an ID list rather than copy, but it's a similar amount of work either way.
The only way I have seen that implemented in Go is with the clipperhouse/gen project,
gen is an attempt to bring some generics-like functionality to Go, with some inspiration from C#’s Linq and JavaScript’s underscore libraries
See this test:
// Distinct returns a new Thing1s slice whose elements are unique. See: http://clipperhouse.github.io/gen/#Distinct
func (rcv Thing1s) Distinct() (result Thing1s) {
appended := make(map[Thing1]bool)
for _, v := range rcv {
if !appended[v] {
result = append(result, v)
appended[v] = true
}
}
return result
}
But, as explained in clipperhouse.github.io/gen/:
gen generates code for your types, at development time, using the command line.
gen is not an import; the generated source becomes part of your project and takes no external dependencies.
You could do something close to this via an interface. Define an interface, say "DeDupable" requiring a func, say, UniqId() []byte, which you could then use to do the removing of dups. and your uniq func would take a []DeDupable and work on it

Resources