N
N
nano_e_t_42017-07-28 16:34:12
go
nano_e_t_4, 2017-07-28 16:34:12

How to sort structure by custom field?

hello
there is a structure

type bla-bla struct {
   a float64
   b float64
   c float64
   d float64
}

and there is an array of structures like this:
func main {
  var la []bla-bla
  var la-la bla-bla
  struct1 := la-la{a: 1.0, b: 3.0, c:3.0, d:1.0}
  struct2 := la-la{a: 0.0, b: 5.0, c:3.0, d:2.0}
  struct3 := la-la{a: 8.0, b: 1.0, c:4.0, d:11.0}
  struct4 := la-la{a: 2.0, b: 0.0, c:3.0, d:7.0}
  la = append(la, struct1)
  la = append(la, struct2)
  la = append(la, struct3)
  la = append(la, struct4)
}

How can I sort them by the field I need?
that is, you need a function of the form:
func sort_structs(la-la []Queries, sort_field) {
  //some_code
}

for example, once you need to sort it by field a. Another time across the field c. And so on
, the function itself was written but for [](map[string]interface{}). Sort the values, then return the corresponding keys. I transferred this function to work with the structure, but the trouble is that I don’t know how to set an arbitrary field for sorting.
If anyone has experienced or knows, please let me know.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
P
Papa, 2017-07-28
Stifflera @PapaStifflera

nerdyworm.com/blog/2013/05/15/sorting-a-slice-of-s...

N
Nikita, 2017-08-01
@bitver

Krch burned...
Here is the documentation of the standard library: https://golang.org/pkg/sort/
Here is a squeeze, for special ones:

once
package main

import (
  "fmt"
  "sort"
)

// A couple of type definitions to make the units clear.
type earthMass float64
type au float64

// A Planet defines the properties of a solar system object.
type Planet struct {
  name     string
  mass     earthMass
  distance au
}

// By is the type of a "less" function that defines the ordering of its Planet arguments.
type By func(p1, p2 *Planet) bool

// Sort is a method on the function type, By, that sorts the argument slice according to the function.
func (by By) Sort(planets []Planet) {
  ps := &planetSorter{
    planets: planets,
    by:      by, // The Sort method's receiver is the function (closure) that defines the sort order.
  }
  sort.Sort(ps)
}

// planetSorter joins a By function and a slice of Planets to be sorted.
type planetSorter struct {
  planets []Planet
  by      func(p1, p2 *Planet) bool // Closure used in the Less method.
}

// Len is part of sort.Interface.
func (s *planetSorter) Len() int {
  return len(s.planets)
}

// Swap is part of sort.Interface.
func (s *planetSorter) Swap(i, j int) {
  s.planets[i], s.planets[j] = s.planets[j], s.planets[i]
}

// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *planetSorter) Less(i, j int) bool {
  return s.by(&s.planets[i], &s.planets[j])
}

var planets = []Planet{
  {"Mercury", 0.055, 0.4},
  {"Venus", 0.815, 0.7},
  {"Earth", 1.0, 1.0},
  {"Mars", 0.107, 1.5},
}

// ExampleSortKeys demonstrates a technique for sorting a struct type using programmable sort criteria.
func main() {
  // Closures that order the Planet structure.
  name := func(p1, p2 *Planet) bool {
    return p1.name < p2.name
  }
  mass := func(p1, p2 *Planet) bool {
    return p1.mass < p2.mass
  }
  distance := func(p1, p2 *Planet) bool {
    return p1.distance < p2.distance
  }
  decreasingDistance := func(p1, p2 *Planet) bool {
    return !distance(p1, p2)
  }

  // Sort the planets by the various criteria.
  By(name).Sort(planets)
  fmt.Println("By name:", planets)

  By(mass).Sort(planets)
  fmt.Println("By mass:", planets)

  By(distance).Sort(planets)
  fmt.Println("By distance:", planets)

  By(decreasingDistance).Sort(planets)
  fmt.Println("By decreasing distance:", planets)

}
two!
package main

import (
  "fmt"
  "sort"
)

type Grams int

func (g Grams) String() string { return fmt.Sprintf("%dg", int(g)) }

type Organ struct {
  Name   string
  Weight Grams
}

type Organs []*Organ

func (s Organs) Len() int      { return len(s) }
func (s Organs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

// ByName implements sort.Interface by providing Less and using the Len and
// Swap methods of the embedded Organs value.
type ByName struct{ Organs }

func (s ByName) Less(i, j int) bool { return s.Organs[i].Name < s.Organs[j].Name }

// ByWeight implements sort.Interface by providing Less and using the Len and
// Swap methods of the embedded Organs value.
type ByWeight struct{ Organs }

func (s ByWeight) Less(i, j int) bool { return s.Organs[i].Weight < s.Organs[j].Weight }

func main() {
  s := []*Organ{
    {"brain", 1340},
    {"heart", 290},
    {"liver", 1494},
    {"pancreas", 131},
    {"prostate", 62},
    {"spleen", 162},
  }

  sort.Sort(ByWeight{s})
  fmt.Println("Organs by weight:")
  printOrgans(s)

  sort.Sort(ByName{s})
  fmt.Println("Organs by name:")
  printOrgans(s)

}

func printOrgans(s []*Organ) {
  for _, o := range s {
    fmt.Printf("%-8s (%v)\n", o.Name, o.Weight)
  }
}

If you really want a miracle - write through reflection. And this is not advice, but an extreme case, I would not advise anyone to use it.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question