Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I'm trying to sort a slice of string, which look like "hour:minute:second".
func main() {
rows := []string{
"1:2:8",
"1:2:5",
"1:2:6",
}
sort.SliceStable(rows, func(i, j int) bool {
var hour_i, min_i, sec_i int
var hour_j, min_j, sec_j int
fmt.Sscanf(rows[i], "%d:%d:%d", &hour_i, &min_i, &sec_i)
fmt.Sscanf(rows[j], "%d:%d:%d", &hour_j, &min_j, &sec_j)
return hour_i < hour_j && min_i < min_j && sec_i < sec_j
})
for _, x := range rows {
fmt.Println(x)
}
}
But the result is same to the input, not sorted. Why is that?
You need to compare each item separately
sort.SliceStable(rows, func(i, j int) bool {
var hour_i, min_i, sec_i int
var hour_j, min_j, sec_j int
fmt.Sscanf(rows[i], "%d:%d:%d", &hour_i, &min_i, &sec_i)
fmt.Sscanf(rows[j], "%d:%d:%d", &hour_j, &min_j, &sec_j)
if hour_i < hour_j {
return true
}
if min_i < min_j {
return true
}
return sec_i < sec_j
})
You can sort your slice using simple sort.Strings() method from sort package,modifying your code and sorting it with the same logic as follows:
package main
import (
"fmt"
"sort"
)
func main() {
rows := []string{
"1:2:8",
"1:2:5",
"1:2:6",
"2:0:7",
"1:0:6",
"2:0:5",
}
sort.Strings(rows)
for _, val := range rows {
fmt.Println(val)
}
}
Output :
1:0:6
1:2:5
1:2:6
1:2:8
2:0:5
2:0:7
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a struct like this:
type structData struct {
dataName string
dataNum int
}
And I have created a slice out of them, like so:
dataSlice := []*structData{}
I have a loop that populates the dataName string and just after this, I want the struct slice to be checked through and duplicates removed.
I mention this specifically because currently, dataNum is 0. So, I don't want to check if the string inside my struct is same or not, it is totally fine checking if the entire struct is equal (if that's possible, else it is also OKAY for me to check duplicates in the dataName string, I just don't know what would look better in design).
An example output of what my struct slice looks like:
&{dataname1 0}
&{dataname1 0}
&{dataname2 0}
&{dataname2 0}
What I want it to look like:
&{dataname1 0}
&{dataname2 0}
You can use a map to check for duplicates, where your struct is the key to the map.
package main
import (
"fmt"
)
type structData struct {
dataName string
dataNum int
}
func (d *structData) String() string {
return fmt.Sprintf("(%s,%d)", d.dataName, d.dataNum)
}
func main() {
dataSlice := []*structData{
{"dataname1", 0},
{"dataname1", 0},
{"dataname2", 0},
{"dataname2", 0},
}
m := map[structData]struct{}{}
dataSlice2 := []*structData{}
for _, d := range dataSlice {
if _, ok := m[*d]; !ok {
dataSlice2 = append(dataSlice2, d)
m[*d] = struct{}{}
}
}
fmt.Printf("%v\n", dataSlice)
fmt.Printf("%v\n", dataSlice2)
}
https://play.golang.org/p/wL-SfBCMGQj
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
How to achieve same thing as the following python code in Go without for loop?
def test(i):
if i == 0:
return None
else:
print(i)
return test(i - 1)
The python function never returns a value:
func test(i int) {
if i==0 {
return
}
fmt.Println(i)
test(i-1)
}
Use a second return value to indicate that the function returned a valid value:
func test(i int) (int, bool) {
if i == 0 {
return 0, false
}
fmt.Println(i)
return test(i - 1)
}
In this specific example, the return value to the top-level caller is always 0, false. Given this, the return value is not needed.
func test(i int) {
if i == 0 {
return
}
fmt.Println(i)
test(i - 1)
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm working on a code to deserialize streams of bytes into objects and I'm stuck on getting the pointer of the field of a struct.
Basically how the code works is as follows: it gets the pointer to a struct, then depending on the type it serializes it, ex. if it's an integer it takes the next 4 bytes. The tricky case is if it's a struct because I have to recursively run Deserialize on all of its attributes and I don't know how to get the address of its field to pass them to Deserialize.
func Deserialize(objPtr interface{}, b []byte) (bytesRead int) {
// it should be the address of the object
val := reflect.ValueOf(objPtr).Elem()
valPtr := reflect.ValueOf(objPtr)
// check if either the object or *object is Serializable
_, isSerializable := (val.Interface()).(Serializable)
_, bo := (valPtr.Interface()).(Serializable)
isSerializable = isSerializable || bo
// specific type serialization
if isSerializable{
return objPtr.(Serializable).Deserializebyte(b)
}
switch val.Kind() {
case reflect.Uint32, reflect.Int, reflect.Int32:
res := reflect.ValueOf(binary.LittleEndian.Uint32(b[:4]))
valPtr.Set(res)
return 4
case reflect.Uint64, reflect.Int64:
res := reflect.ValueOf(binary.LittleEndian.Uint32(b[:8]))
valPtr.Set(res)
return 8
case reflect.Struct:
n_bytes := 0
for i := 0; i < val.NumField(); i++ {
// stuck in here
valPtr.Elem()
// I don't think the next line works
last_n_bytes := Deserialize(&(valPtr.Elem().Field(i).Interface()), b)
n_bytes += last_n_bytes
b = b[last_n_bytes:]
}
//valPtr.Set(res)
return n_bytes
default:
panic("this panic is for debug, every case should be handled above")
res := val.Bytes()
valPtr.Set(res)
return len(val.Bytes())
}
return 0
}
Use the reflect API to get the address of the field:
last_n_bytes := Deserialize(valPtr.Elem().Field(i).Addr().Interface(), b)
The superint example panics because the application takes the address of an unexported field through the reflect API. That's not allowed because it would allow another package to modify the field.
Here's a working example with exported fields:
type superint struct {
A int
B int
}
func (s *superint) lol() {}
type a interface{ lol() }
func main() {
i := superint{A: 1, B: 9}
valPtr := reflect.ValueOf(&i)
fmt.Printf("%v \n", &i.A)
fmt.Printf("%v \n", valPtr.Elem().Field(0).Addr().Interface())
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have a map string that looks like this
map[first:[hello] second:[world]]
The problem is that when I iterate over it and return the values they return [hello] [world] and I want them to just return hello world
// currentMap is of type map[interface{}]interface{} originally
newStringMap := make(map[string]interface{})
for k, v := range currentMap {
newStringMap[k.(string)] = v
}
return newStringMap
How can this be done?
From the below information provided by you:
when I iterate over it and return the values they return [hello] [world]
It seems that your currentMap actually stores string slices []string as values, behind the interface{} type. Assuming that above line means that you see this when printing the map using fmt.Println(), or similar functions.
map[first:[hello] second:[world]]
Here's a possible reproduction & solution of your problem::
package main
import (
"fmt"
)
func main() {
currentMap := make(map[interface{}]interface{})
currentMap["first"] = []string{"hello"}
currentMap["second"] = []string{"world"}
newStringMap := make(map[string]interface{})
fmt.Println("Problem:")
fmt.Printf("%v\n", currentMap)
fmt.Println("\nSolution:")
for k, v := range currentMap {
lst, ok := v.([]string)
//fmt.Println(lst, ok)
if ok && len(lst) > 0 {
newStringMap[k.(string)] = v.([]string)[0]
} else {
newStringMap[k.(string)] = nil
}
}
fmt.Printf("%v\n", newStringMap)
}
Which outputs to:
Problem:
map[first:[hello] second:[world]]
Solution:
map[first:hello second:world]
Try it here
https://play.golang.org/p/5XAA3m6MDX_b
It's not necessary that the content stored in currentMap is always of similar type. (if it is, then why would interface{} ever be used). Which means, don't forget your error-checking. I have tried to cover the same. You may need to add some more, based on the possible actual types in the map, similar to this section:
if ok && len(lst) > 0 {
newStringMap[k.(string)] = v.([]string)[0]
} else {
newStringMap[k.(string)] = nil
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I have the following code and ask my self is this the "go way" to solve the following requirement.
I need to print a directory tree sorted by file age.
package main
import (
"fmt"
"github.com/kr/fs"
"os"
"time"
"sort"
)
type fileinfo struct {
Path string
age time.Duration
}
func main() {
fmt.Print("test range of fs")
walker := fs.Walk("../")
var files []fileinfo
for walker.Step() {
if err := walker.Err(); err != nil {
fmt.Fprintln(os.Stderr, err)
continue
}
age := time.Now().Sub(walker.Stat().ModTime())
files = append(files,fileinfo{walker.Path(),age})
}
sort.Slice(files, func(i, j int) bool {
return files[i].age < files[j].age
})
for i:=0; i < len(files) ; i++ {
fmt.Print("File path: ",files[i].Path," age: ",files[i].age,"\n")
}
}
What's your opinion to the code?
Thanks for help
for i:=0; i < len(files) ; i++ {
fmt.Print("File path: ",files[i].Path," age: ",files[i].age,"\n")
}
for loops over arrays are better written using range iterator. This makes the code easier to read, avoids silly mistakes, and it works with other structures like maps and channels.
for _,file := range files {
fmt.Print("File path: ",file.Path," age: ",file.age,"\n")
}
See Go by Example: Range for more.
Since you have a newline at the end and a space between each element, fmt.Println might work out better than fmt.Print. It automatically puts spaces between each element and a newline at the end.
fmt.Println("File path:", file.Path, "age:", file.age)