how to get lonely value from a slice golang [duplicate] - go

This question already has answers here:
How to remove duplicates strings or int from Slice in Go
(12 answers)
How to delete duplicates of an item from a slice?
(3 answers)
how to delete Duplicate elements between slices on golang
(1 answer)
Closed 10 months ago.
I want to create a function that can retrieve data that has no duplicates from a slice
an example of a slice that will be processed:
number1 := []int{3,4,5,4,3}
number2 := []int{3,4,5,6,4,3}
expected result :
res1 = []int{5}
res2 = []int{5,6}
i have do something like this
func unique(arg []int) []int {
var inResult = make(map[int]bool)
var result []int
for _, value := range arg {
if _, ok := inResult[value]; !ok {
inResult[value] = true
result = append(result, value)
} else {
inResult[value] = false
}
}
fmt.Println(inResult)
return result
}
func main() { arg := []int{6, 6, 7, 1, 2, 3, 4, 5, 3, 2, 1}
res := unique(arg)
fmt.Println(res)
}
how to get the key from map where the value is true?
map[1:false 2:false 3:false 4:true 5:true 6:false 7:true]
[6 7 1 2 3 4 5]

You can filter out the keys like this.
Remove the following line in if block. It should be done after the complete iteration.
result = append(result, value)
Filter the keys with having true value before returning result.
for key, value := range inResult {
if value {
result = append(result, key)
}
}
Go Playground

Related

How to insert element at the beginning of a slice? [duplicate]

This question already has answers here:
How to prepend int to slice
(4 answers)
Closed last year.
I have a slice:
mySlice := []int{4,5,6,7}
myelement := 3
I want to insert myelement at index 0 so that my output will be [3,4,5,6,7].
How can I do that?
you can use the append property here.
first, need to make a slice with the myelement. then append the slice in mySlice
mySlice = append(myelement, mySlice...)
this is the function that will return the myelement inserting in the first place of the slice.
func addElementToFirstIndex(x []int, y int) []int {
x = append([]int{y}, x...)
return x
}
See
func addFirst(s []int, insertValue int) []int {
res := make([]int, len(s)+1)
copy(res[1:], s)
res[0] = insertValue
return res
}
Another solution, former answers are better.

How to implement remove range on string array golang?

How can I implement RemoveRange method in golang? It is a method in C# as shown here
I want to implement RemoveRange method on my hashCode string array and return new modified array back if possible with those ranges remove.
func removeRange(hashCode []string, idx int, count int) []string {
var temp []string
for i, s := range hashCode {
fmt.Println(i, s)
// confuse here on what to do
}
return temp
}
Simply slice the slice up until idx, skip count elements and append the rest to the result of the first slicing:
func removeRange(hashCode []string, idx int, count int) []string {
return append(hashCode[:idx], hashCode[idx+count:]...)
}
Testing it:
s := []string{"0", "1", "2", "3", "4", "5"}
fmt.Println(s)
s = removeRange(s, 1, 2)
fmt.Println(s)
Which outputs (try it on the Go Playground):
[0 1 2 3 4 5]
[0 3 4 5]
Note: the above implementation does not check whether indices are valid (whether they are in range). If not, the code could panic. Add necessary checks if you need to.
Note #2: the above implementation modifies the elements of the passed slice, the returned slice will share the backing array of the parameter. If you want to avoid this, if you want to leave the input intact and allocate a new slice for the result, then do so:
func removeRange(hashCode []string, idx int, count int) []string {
result := make([]string, 0, len(hashCode)-count)
result = append(result, hashCode[:idx]...)
result = append(result, hashCode[idx+count:]...)
return result
}
Try this one on the Go Playground.
You don't need a method or function for this at all in golang. Go slices can be subsliced and appended in place, which is how you can quickly and easily remove subsets from any slice.
Say you want to remove 2 elements, starting at index 2, you'd simply write:
Sub := append(original [:2], original [4:]...)
Demo
How this works:
original[:2] creates a sub-slice starting at 0, with a length of 2 elements (so index 0 and 1)
append because to this first part, we want to add the rest of the slice, minus the range we want to skip/remove
original[4:] creates another sub-slice, this time starting at index 4, and ending wherever original ends. Just like we don't explicitly mention 0 as the starting point in the first sub-slice, by not specifying a number of elements here, golang will just include all of the remaining elements in the slice.
... because append is a variadic function (built-in, but you get the point), we need to pass in every element we want to append as a new argument. The ... operator expands the sub-slice and passes in every element as a separate argument.
Because we assigned the new slice to a new variable, original will remain unchanged, so if you want to overwrite the slice, you just assign it to the same variable.
Note I wrote this on my phone, so markup and code may not be quite right, but this should answer your question at least
I've explained the code using // comments and if not commented, code is self explanatory.
package main
import (
"fmt"
"os"
)
func RemoveRange(s []string, index, count int) []string {
sLen := len(s)
// Similar semantics to match (similar) the behavior of
// C# implementation
switch {
case index < 0, count < 0: // arguments are not valid
fmt.Fprintln(os.Stderr, "error: argument out of range error")
return s
case index+count-1 >= sLen: // range results in exceeding the limit
fmt.Fprintln(os.Stderr, "error: argument error")
return s
}
// Create a slice p and pre-allocate the size required
// to store the resultant slice after removing range.
// Result := s[:] -> s[:index] + s[index+count:]
// Remove := s[index:index+count-1]
p := make([]string, 0, sLen-count)
p = append(p, s[:index]...)
p = append(p, s[index+count:]...)
return p
}
func main() {
s := []string{"0", "1", "2", "3", "4", "5"}
fmt.Println(s)
r := RemoveRange(s, 1, 3)
fmt.Println(r)
}
Output:
[0 1 2 3 4 5]
[0 4 5]

How to get single items count in a slice with go?

For example, this is a slice:
[1, 2, 3, 3, 4]
want to get single data 1, 2, 4 's count and return count = 3.
Maybe remove duplicate items(include itself) is an idea, but didn't find suitalbe method.
What I tried:
func removeDuplicateItems() {
intSlice := []int{1, 2, 3, 3, 4}
fmt.Println(intSlice)
keys := make(map[int]bool)
list := []int{}
for _, entry := range intSlice {
if _, value := keys[entry]; !value {
keys[entry] = true
list = append(list, entry)
}
}
fmt.Println(list)
}
Got
[1 2 3 3 4]
[1 2 3 4]
I just changed your function a little bit:
func removeDuplicateItems() {
intSlice := []int{1, 2, 3, 3, 4}
fmt.Println(intSlice)
keys := make(map[int]int)
list := []int{}
for _, entry := range intSlice {
keys[entry]++
}
for k, v := range keys {
if v == 1 {
list = append(list, k)
}
}
fmt.Println(list)
}
https://play.golang.org/p/ESFLhC4VC-l
At this point the list is not sorted. If you want to sort your list afterward you need to use the sortpackage.
I suppose a really easy & quick way to get the count of unique values would be to use a map:
data := map[int]bool{}
cnt := 0 // count of unique values
for _, i := range intSlice {
if dup, ok := data[i]; !ok {
// we haven't seen value i before, assume it's unique
data[i] = false // add to map, mark as non-duplicate
cnt++ // increment unique count
} else if !dup {
// we have seen value i before, but this is only the second time
cnt-- // unique count goes down here
data[i] = true // mark this value as known duplicate
}
}
At the end of this loop, you'll have cnt with the count of unique values, and you can iterate the map data for all keys with value false to get the unique values that you found in the slice. All keys combined basically are the values in the slice, de-duplicated.

How to delete item from a slice? [duplicate]

This question already has answers here:
Delete element in a slice
(7 answers)
Closed 7 years ago.
I have a slice of strings, and I want to remove a specific one.
strings := []string
strings = append(strings, "one")
strings = append(strings, "two")
strings = append(strings, "three")
Now how can I remove the string "two" from strings?
Find the element you want to remove and remove it like you would any element from any other slice.
Finding it is a linear search. Removing is one of the following slice tricks:
a = append(a[:i], a[i+1:]...)
// or
a = a[:i+copy(a[i:], a[i+1:])]
Here is the complete solution (try it on the Go Playground):
s := []string{"one", "two", "three"}
// Find and remove "two"
for i, v := range s {
if v == "two" {
s = append(s[:i], s[i+1:]...)
break
}
}
fmt.Println(s) // Prints [one three]
If you want to wrap it into a function:
func remove(s []string, r string) []string {
for i, v := range s {
if v == r {
return append(s[:i], s[i+1:]...)
}
}
return s
}
Using it:
s := []string{"one", "two", "three"}
s = remove(s, "two")
fmt.Println(s) // Prints [one three]
Here is a function to remove the element at a particular index:
package main
import "fmt"
import "errors"
func main() {
strings := []string{}
strings = append(strings, "one")
strings = append(strings, "two")
strings = append(strings, "three")
strings, err := remove(strings, 1)
if err != nil {
fmt.Println("Something went wrong : ", err)
} else {
fmt.Println(strings)
}
}
func remove(s []string, index int) ([]string, error) {
if index >= len(s) {
return nil, errors.New("Out of Range Error")
}
return append(s[:index], s[index+1:]...), nil
}
Try it on Go Playground

Is there a foreach loop in Go?

Is there a foreach construct in the Go language?
Can I iterate over a slice or array using a for?
From For statements with range clause:
A "for" statement with a "range" clause iterates through all entries
of an array, slice, string or map, or values received on a channel.
For each entry it assigns iteration values to corresponding iteration
variables and then executes the block.
As an example:
for index, element := range someSlice {
// index is the index where we are
// element is the element from someSlice for where we are
}
If you don't care about the index, you can use _:
for _, element := range someSlice {
// element is the element from someSlice for where we are
}
The underscore, _, is the blank identifier, an anonymous placeholder.
Go has a foreach-like syntax. It supports arrays/slices, maps and channels.
Iterate over an array or a slice:
// index and value
for i, v := range slice {}
// index only
for i := range slice {}
// value only
for _, v := range slice {}
Iterate over a map:
// key and value
for key, value := range theMap {}
// key only
for key := range theMap {}
// value only
for _, value := range theMap {}
Iterate over a channel:
for v := range theChan {}
Iterating over a channel is equivalent to receiving from a channel until it is closed:
for {
v, ok := <-theChan
if !ok {
break
}
}
Following is the example code for how to use foreach in Go:
package main
import (
"fmt"
)
func main() {
arrayOne := [3]string{"Apple", "Mango", "Banana"}
for index,element := range arrayOne{
fmt.Println(index)
fmt.Println(element)
}
}
This is a running example https://play.golang.org/p/LXptmH4X_0
Yes, range:
The range form of the for loop iterates over a slice or map.
When ranging over a slice, two values are returned for each iteration. The first is the index, and the second is a copy of the element at that index.
Example:
package main
import "fmt"
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
for i := range pow {
pow[i] = 1 << uint(i) // == 2**i
}
for _, value := range pow {
fmt.Printf("%d\n", value)
}
}
You can skip the index or value by assigning to _.
If you only want the index, drop the , value entirely.
The following example shows how to use the range operator in a for loop to implement a foreach loop.
func PrintXml (out io.Writer, value interface{}) error {
var data []byte
var err error
for _, action := range []func() {
func () { data, err = xml.MarshalIndent(value, "", " ") },
func () { _, err = out.Write([]byte(xml.Header)) },
func () { _, err = out.Write(data) },
func () { _, err = out.Write([]byte("\n")) }} {
action();
if err != nil {
return err
}
}
return nil;
}
The example iterates over an array of functions to unify the error handling for the functions. A complete example is at Google´s playground.
PS: it shows also that hanging braces are a bad idea for the readability of code. Hint: the for condition ends just before the action() call. Obvious, isn't it?
You can in fact use range without referencing its return values by using for range against your type:
arr := make([]uint8, 5)
i,j := 0,0
for range arr {
fmt.Println("Array Loop", i)
i++
}
for range "bytes" {
fmt.Println("String Loop", j)
j++
}
https://play.golang.org/p/XHrHLbJMEd
This may be obvious, but you can inline the array like so:
package main
import (
"fmt"
)
func main() {
for _, element := range [3]string{"a", "b", "c"} {
fmt.Print(element)
}
}
outputs:
abc
https://play.golang.org/p/gkKgF3y5nmt
I'm seeing a lot of examples using range. Just a heads up that range creates a copy of whatever you're iterating over. If you make changes to the contents in a foreach range you will not be changing the values in the original container, in that case you'll need a traditional for loop with an index you increment and deference indexed reference. E.g.:
for i := 0; i < len(arr); i++ {
element := &arr[i]
element.Val = newVal
}
I have just implemented this library: https://github.com/jose78/go-collection.
This is an example of how to use the Foreach loop:
package main
import (
"fmt"
col "github.com/jose78/go-collection/collections"
)
type user struct {
name string
age int
id int
}
func main() {
newList := col.ListType{user{"Alvaro", 6, 1}, user{"Sofia", 3, 2}}
newList = append(newList, user{"Mon", 0, 3})
newList.Foreach(simpleLoop)
if err := newList.Foreach(simpleLoopWithError); err != nil{
fmt.Printf("This error >>> %v <<< was produced", err )
}
}
var simpleLoop col.FnForeachList = func(mapper interface{}, index int) {
fmt.Printf("%d.- item:%v\n", index, mapper)
}
var simpleLoopWithError col.FnForeachList = func(mapper interface{}, index int) {
if index > 1{
panic(fmt.Sprintf("Error produced with index == %d\n", index))
}
fmt.Printf("%d.- item:%v\n", index, mapper)
}
The result of this execution should be:
0.- item:{Alvaro 6 1}
1.- item:{Sofia 3 2}
2.- item:{Mon 0 3}
0.- item:{Alvaro 6 1}
1.- item:{Sofia 3 2}
Recovered in f Error produced with index == 2
ERROR: Error produced with index == 2
This error >>> Error produced with index == 2
<<< was produced
Try this code in playGrounD.

Resources