Sort slice on number of occurrences of a value - sorting

Please see this playground. I have a slice with some data. Now I want to sort this slice, but not on a value inside one of the values, but I want to sort it on the number of occurrences of one of the values.
Unfortunately I don't have a clue how to fix this. Can someone please point me to the right direction?
I know I can do this:
sort.Slice(messages, func(i, j int) bool {
return messages[i].SupplierID < messages[j].SupplierID
})
This will sort the slice, but it will start with the "higest" supplierID. but what I want is to sort on the number of occurrences: the ones with the lease number of supplierIDs first.

Iterate over the slice, populate a map of occurrences, then sort the slice based on the number of occurrences:
supplierCounts := make(map[int]int)
for _, msg := range messages {
supplierCounts[msg.SupplierID]++
}
sort.Slice(messages, func(i, j int) bool {
return supplierCounts[messages[i].SupplierID] < supplierCounts[messages[j].SupplierID]
})
https://play.golang.org/p/YMWPP2JBC2P

Related

How do I print a 2-Dimensional array as a grid in Golang?

The 2D Array I am trying to print as a board
Note: I am a complete novice at using Go and need this for a final project.
I am making an attempt to make the game, snake and ladders. I need to print a 10x10 2D array as a grid so it can look more like a board.
I've tried using:
for row := 0; row < 10; row ++ 10{
} for column := 0; column < 10; column++{
fmt.Println()
}
But it fails.
Any function or any method to do so?
You are almost there, you should pass the variable you want to print to fmt.Println. Also keep in mind that this will always add a newline to the end of the output. You can use the fmt.Print function to just print the variable.
for row := 0; row < 10; row++ {
for column := 0; column < 10; column++{
fmt.Print(board[row][column], " ")
}
fmt.Print("\n")
}
Bonus tip, instead of using hardcoded sizes you can also use range to loop over each element which works for arrays/slices of any size.
Range-Based Solution
Ranges save us from passing the length directly, and so could make the function re-usable for 2D arrays of differing heights and widths. (Go By Example range page).
A general purpose 2D matrix iterator
Using a range to loop over every value in a 2D array might look like ...
Run this code in Go playground here
// Code for some "board" matrix of type [][]int, for example...
board := [][]int{
{1, 2, 3},
{4, 5, 6},
}
// First we iterate over "board", which is an array of rows:
for r, _ := range board {
// Then we iterate over the items of each row:
for c, colValue := range board[r] {
// See string formatting docs at
// https://gobyexample.com/string-formatting
fmt.Printf("value at index [%d][%d]", r, c)
fmt.Println(" is", colValue)
}
}
What the underscores mean
Underscores are necessary where declared variables would not be used, or the (compiler?) will throw an error and won't run the code.
The variables r and c are used to give us ongoing access to integer indexes within the matrix, starting at 0 and counting up. We have to pass an underscore _ there after the r because that space would give us access to the whole row object, which we don't ever use later in the code. (Yes, we could alternatively have defined range row instead of range board[r], and then we would be using the row object. )
We also would have had to pass a _ in position of c if we hadn't later used c in the Printf statement. Here is a simpler version (and Go Playground) with no index-access:
// Just prints all the values.
for _, row := range board {
for _, colValue := range row {
fmt.Println(colValue)
}
}
why is "colValue" and not "col" ?
In this pattern, some telling name like "colValue" is used instead of column. This is because at this inner point in the code, we have drilled down to a single element instead of a whole set of elements like by accessing whole rows with board[r]
Here, we don't use the indices at all, so they have to be written with _.

Add []bytes append slice []bytes

I began to learn the language of GO and I do not quite understand something, maybe I'm just confused and tired.
Here is my code, there is an array of result (from encoded strings, size 2139614 elements). I need to decode them and use them further. But when I run an iteration, the resultrips is twice as large and the first half is completely empty. Therefore, I make a slice and add to it the desired range.
Why it happens?
It might be easier to decode the result immediately and re-record it, but I don’t know how to do it, well)))
maybe there is a completely different way and as a beginner I don’t know it yet
result := []string{}
for i, _ := range input {
result = append(result, i)
}
sort.Strings(result)
rips := make([][]byte, 2139614)
for _, i := range result {
c := Decode(i)
c = c[1:37]
rips = append(rips, c)
}
//len(result) == 2139614
for i := 2139610; i < 2139700; i++ {
fmt.Println(i, rips[i])
}
resultrips := rips[2139614:]
for _,i := range resultrips {
fmt.Println(i)
}
fmt.Println("All write: ", len(resultrips))
and this question: I do it right if I need an array of byte arrays (I do it so as not to do too much work and will check the values in bytes, because there is no any coding) ???
rips := make([][]byte, 2139614) //array []byte
in the end, I need an array of the type of the set in C ++ to check if there is an element in my set
in C ++ it was code:
if (resultrips.count > 0) { ... }
When you write:
make([][]byte, 2139614)
This creates a slice with length and capacity equal to 2139614. When you append to a slice, it always appends after the last element, thereby increasing the length. If you want to pre-allocate a large slice so that you can append into it, you want to specify a length of 0:
make([][]byte, 0, 2139614)
This pre-allocates 2139614 elements, but with a length of 0, subsequent append calls will start at the beginning of the slice; after the first append it will have a length of 1, and it will not need to have increased its capacity.
Length vs capacity is covered in the Tour of Go: https://tour.golang.org/moretypes/13
A quick note based on the text of your question - remember that slices and arrays are not the same thing. Arrays have a compile-time fixed length and their capacity is synonymous with their length. Slices are backed by arrays but have runtime dynamic independent length and capacity.

Remove elements from priority queue in golang

I take the full realization of priority queue from golang docs. I'm interesting in removing several elements at once like heap.Remove(&queue, index1, index2, ...).
Now it can be done in the straightforward way:
for _, event := range events {
heap.Remove(&queue, event.getIndex())
}
But this method has an overhead because every call to heap.Remove reorganizes tree. It seems more efficient if we can remove all unnecessary elements firstly and only then reorganize tree.
How it can be implemented?
Since the underlying data structure of your heap is a slice, you can remove the elements directly from the slice and re-initialize the heap again after.
Starting from your example:
for _, event := range events {
i := event.GetIndex()
queue[i], queue[len(queue)-1] = queue[len(queue)-1], queue[i]
queue = queue[:len(queue)-1]
}
heap.Init(&queue)
And a working example: https://play.golang.org/p/-KMEilCm3t9
func main() {
h := IntHeap{1, 5, 2, 9, 8, 3, 7}
toRemove := 8
for i := 0; i < len(h); i++ {
n := h[i]
if n == toRemove {
h[i], h[len(h)-1] = h[len(h)-1], h[i]
h = h[:len(h)-1]
i--
}
}
heap.Init(&h)
fmt.Println(h)
}
In order to answer this question we first need to understand what a heap is. Heaps are a data structure that allow us to find the largest or smallest value depending on whether it is a Min Heap or a Max Heap. To do this quickly, the computer maintains a tree, this image sums it up quite well. This is a max heap:
Of course computer's memory aren't laid out in trees, they are laid out linearly. In fact, go stores heaps in slices, which means that you can iterate through the slice and remove elements like you'd normally do, for example:
for i:=0; i<len(heap); i++ {
for _, element := heap {
if element == to_remove {
heap = append(heap[:i], heap[i+1:])
i--
}
}
}

Sort slice of maps

I have a slice of 10 maps, how can I sort by one of the values?
[{"name":"a","score":100},
{"name":"z","score":150},
{"name":"s","score":120},
{"name":"x","score":110},
{"name":"r","score":10},
{"name":"b","score":1300},
{"name":"b","score":1500},
{"name":"w","score":1002},
{"name":"o","score":140},
{"name":"q","score":101}]
I want to sort the slice with the score value, in descending order, but I'm at a loss of how.
just a simple sort.Slice.
sort.Slice(information,
func(i, j int) bool {
return information[i].Difference > information[j].Difference
})

slice iteration order in go

Ok, i think this may be an old question, but i didn't find anything over the stackoverflow. In go , the iteration order over a map is not guranteed to be reproducible. So, the way suggest is to hold the keys in a slice and sort that slice. Then iterate over that slice to retrieve the values from the map, so that we get them in order(since slice composed of keys is sorted, so will be in reproducible order). So this goes to imply that the slice need be sorted else iteration over the slice will also not give reproducible order. But when i tried the below code in playground, i always found the order maintained in iteration, then in the map iteration case, why the slice of keys need to be sorted?
func main() {
var mySlice = make([]string, 0)
mySlice = append(mySlice, "abcd")
mySlice = append(mySlice, "efgh")
mySlice = append(mySlice, "ijkl")
mySlice = append(mySlice, "mnop")
mySlice = append(mySlice, "qrst")
mySlice = append(mySlice, "uvwxyz")
for _, val := range mySlice {
fmt.Println(val)
}
fmt.Println(strings.Join(mySlice, "|"))
}
Output:
abcd
efgh
ijkl
mnop
qrst
uvwxyz
abcd|efgh|ijkl|mnop|qrst|uvwxyz
A slice or array will always have a fixed order, i.e. how it is laid out in memory.
The documentation you were reading was probably just telling you to sort the slice so that the map output is in sorted order.
You are correct that the iteration order of a map is undefined and hence can be different each time it is performed. If you use a slice to iterate a map then it will always come back in a reliable order, i.e. the order of the keys in the slice.
I suggest you have a read over the information about slices.
EDIT
If it helps, consider the following code to illustrate that the sorting of a slice has nothing to do with its order being fixed:
words := map[int]string{
0: "hello",
1: "there",
2: "goodbye",
}
keys:=[]int{2,0,1}
for _, k := range keys {
// Will output in order: Goodbye, hello, there
fmt.Println("Key:", k, "Value:", words[k])
}
The only reason your slice is sorted is because you're appending items in already sorted order. If you appended items in an unsorted order like this
var mySlice = make([]string, 0)
mySlice = append(mySlice, "mnop")
mySlice = append(mySlice, "efgh")
mySlice = append(mySlice, "uvwxyz")
mySlice = append(mySlice, "ijkl")
mySlice = append(mySlice, "abcd")
mySlice = append(mySlice, "qrst")
(or populated a slice by pulling keys from a map, which would be unsorted), then the order on iteration would be unsorted (consistent, yes, but consistently unsorted). So, if your objective is to use the slice to pull items from a map in sorted order, then you need to first sort the slice, unless you can guarantee the slice items were inserted in an already sorted order.

Resources