I wrote a function to find the loop in a list using golang. But I am not able to construct a loop in a list as input.
Please find below the code,
package main
import (
"container/list"
"fmt"
)
func main() {
l := list.New()
l.PushBack(0)
l.PushBack(1)
l.PushBack(2)
l.PushBack(3)
l.PushBack(4)
l.PushBack(5)
e6 := l.PushBack(6)
l.PushBack(7)
e8 :=l.PushBack(8)
e9 := l.InsertAfter(9,e8)
l.InsertBefore(e9, e6)
for e:=l.Front() ; e !=nil ; e=e.Next() {
fmt.Println(e.Value)
}
}
could anyone help me on this?
It is not possible to construct a loop using the container/list List type. The List type methods ensure that there's no loop. Because the list Element's next and previous pointers are not exported, the application cannot create a loop by modifying the elements directly.
You can define your own type to create a list with a loop:
package main
import "fmt"
type node struct {
v int
next *node
}
func main() {
// Create list with 1, 2, 3 and print.
l := &node{1, &node{2, &node{3, nil}}}
for n := l; n != nil; n = n.next {
fmt.Println(n.v)
}
// Create list with loop and print at most 100 steps down the list.
n3 := &node{3, nil}
l = &node{1, &node{2, n3}}
n3.next = l
for i, n := 0, l; n != nil && i < 100; n, i = n.next, i+1 {
fmt.Println(n.v)
}
}
playground example
Related
In a test function, there is a case where nested slices should be compared.
Say I have two varibles like the following:
want := [][]string{{"bat"},{"nat","tan"},{"ate","eat","tea"}}
got := [][]string{{"eat","tea","ate"},{"tan","nat"},{"bat"}}
How can compare them?
First, I used reflect.DeepEqual which was wrong, I also tried go-cmp:
t.Run(tt.name, func(t *testing.T) {
opt := cmpopts.SortSlices(func (a, b []int) bool {
// not sure what to write
})
if got := groupAnagrams(tt.args.strs); !cmp.Equal(got, tt.want, opt) {
t.Errorf("groupAnagrams() = %v, want %v", got, tt.want)
}
})
Sort the inner slices:
for _, s := range want { sort.Strings(s) }
for _, s := range got { sort.Strings(s) }
Sort the outer slices:
sortOuter(want)
sortOuter(got)
where sortOuter is a the function:
func sortOuter(s [][]string) {
sort.Slice(s, func(a, b int) bool {
sa := s[a]
sb := s[b]
n := len(sa)
if n > len(sb) {
n = len(sb)
}
for i := 0; i < n; i++ {
if sa[i] != sb[i] {
return sa[i] < sb[i]
}
}
return len(sa) < len(sb)
})
}
Compare:
fmt.Println(reflect.DeepEqual(got, want))
https://go.dev/play/p/SjN8gLmotjd
You can sort inner slices using sort.Slice as below and check if outer slices are equal using testify assert.ElementsMatch:
func TestXxx(t *testing.T) {
// Slices
want := [][]string{{"bat"}, {"nat", "tan"}, {"ate", "eat", "tea"}}
got := [][]string{{"eat", "tea", "ate"}, {"tan", "nat"}, {"bat"}}
// Running tests
t.Run("test", func(t *testing.T) {
// Sorting got inners
for _, inner := range got {
sort.Slice(inner, func(i, j int) bool {
return inner[i] < inner[j]
})
}
// Sorting want inners
for _, inner := range want {
sort.Slice(inner, func(i, j int) bool {
return inner[i] < inner[j]
})
}
// Match
assert.ElementsMatch(t, got, want)
})
}
ElementsMatch:
ElementsMatch asserts that the specified listA(array, slice...) is equal to specified listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, the number of appearances of each of them in both lists should match.
assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
List<int> myList = [1,2,3];
int i = 2;
myList[i] = 4; // myList = [1,2,4]
but what if i don't know whether myList contains data at specific index? Then it gives me range error.
i = 4;
myList[i] = 4 // range error
if(myList[i] != null) myList[i] = 4 //range error
myList.insert(i, 4) // i want to replace, not shift values.
Is the only way to replace the list value at specific index is by checking the whole list length first?
Here is the example that you can check the index before and If that condition is true then only it will update the value.
void main() {
List<int> myList1 = [1,2,3];
int i = 2;
if(myList1.length> i) myList1[i] = 4; // myList = [1,2,4]
myList1.forEach(print);
int j = 5;
if(myList1.length> j) myList1[j] = 4; // myList = [1,2,4]
myList1.forEach(print); // It will print as it is last one.
}
Thank you.
From what I understood, you want to know if there is any other way to check whether or not the index exists for your list.
If So then:
List<int> myList = [1,2,3];
int i = 2;
if(myList.asMap().containsKey(i)) myList[i] = 4
Let me know if I understood your question correctly.
try like this:
if(i<=myList.length){
myList[i]=4;
}
In Python, I have the following:
i = series.index(s) # standard Python list.index() function
tmp = series.pop(i)
blah = f(tmp)
series.append(tmp)
In converting this to Go, I am looking for a similar way of retrieving an item from a slice by index, doing something with it, then putting the original item at the end of my slice.
From here, I have arrived at the following:
i = Index(series, s) // my custom index function...
tmp, series = series[i], series[i+1:]
blah := f(tmp)
series = append(series, tmp)
But this fails at the end of lists:
panic: runtime error: slice bounds out of range
How would I idiomatically translate this slice.pop() into Go?
The "Cut" trick in the linked document does what you want:
xs := []int{1, 2, 3, 4, 5}
i := 0 // Any valid index, however you happen to get it.
x := xs[i]
xs = append(xs[:i], xs[i+1:]...)
// Now "x" is the ith element and "xs" has the ith element removed.
Note that if you try to make a one-liner out of the get-and-cut operations you'll get unexpected results due to the tricky behavior of multiple assignments in which functions are called before other expressions are evaluated:
i := 0
x, xs := xs[i], append(xs[:i], xs[i+1:]...)
// XXX: x=2, xs=[]int{2, 3, 4, 5}
You can work around by wrapping the element access operation in any function call, such as the identity function:
i := 0
id := func(z int) { return z }
x, xs := id(xs[i]), append(xs[:i], xs[i+1:]...)
// OK: x=1, xs=[]int{2, 3, 4, 5}
However, at that point it's probably more clear to use separate assignments.
For completeness, a "cut" function and its usage could look like this:
func cut(i int, xs []int) (int, []int) {
y := xs[i]
ys := append(xs[:i], xs[i+1:]...)
return y, ys
}
t, series := cut(i, series)
f(t)
series = append(series, t)
If you want to write a function that does pop() in a similar way to python then you'll have to pass in a pointer to the object so the object can be modified, as pop both returns the value and alters the list
func pop(alist *[]int) int {
f:=len(*alist)
rv:=(*alist)[f-1]
*alist=(*alist)[:f-1]
return rv
}
func main() {
n:=[]int{1,2,3,4,5}
fmt.Println(n)
last:=pop(&n)
fmt.Println("last is",last)
fmt.Printf("list of n is now %v\n", n)
You can declaretype intSlice []int and you can declare method pop() using that pointer receiver: func (l *intSlice) pop() int. Then you can call .pop() on instance of intSlice object. This becomes stylistically more similar to Python.
package main
import (
"fmt"
)
type intSlice []int
func (l *intSlice) pop() int {
length := len(*l)
lastEle := (*l)[length-1]
*l = (*l)[:length-1]
return lastEle
}
func main() {
mySlice := intSlice{1, 2, 3, 4, 5, 6}
popped := mySlice.pop()
fmt.Println(popped)
fmt.Println(mySlice)
popped = mySlice.pop()
fmt.Println(popped)
fmt.Println(mySlice)
}
Result:
6
[1 2 3 4 5]
5
[1 2 3 4]
Go Playground
I'm not sure there's a direct equivalent of "pop()" ... but you can do something like this:
A Tour of Go
Slices can be created with the built-in make function; this is how
you create dynamically-sized arrays.
The make function allocates a zeroed array and returns a slice that
refers to that array:
a := make([]int, 5) // len(a)=5
To specify a capacity, pass a third argument to make:
b := make([]int, 0, 5) // len(b)=0, cap(b)=5
b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:] // len(b)=4, cap(b)=4
See also:
https://blog.golang.org/go-slices-usage-and-internals
cap vs len of slice in golang
I'd do something similar to what paulsm4 suggested:
package main
import (
"fmt"
)
func main() {
a := []int{1,2,3,4,5}
i,b := pop(a)
fmt.Println(i,b) // 5 [1 2 3 4]
}
func pop(a []int) (int,[]int) {
return a[len(a)-1],a[:len(a)-1]
}
Go playground
Another option would be to create a function that takes a pointer to an int slice which modifies the argument to remove the last value and return it:
func pop(xs *[]int) int {
x := (*xs)[len(*xs)-1] // Store the last value to return.
*xs = (*xs)[:len(*xs)-1] // Remove the last value from the slice.
return x
}
For example (Go Playground):
xs := []int{1, 2, 3} // => xs=[1, 2, 3]
x := pop(&xs) // => xs=[1, 2], x=3
I have a list of directions and want to find the next direction when I take a right or left turn. Here is the working code I have:
enum class Turn { R, L }
enum class Direction { N, E, S, W }
val directionsInRightTurnOrder = listOf(Direction.N, Direction.E, Direction.S, Direction.W)
private fun calculateNextHeading(heading: Direction, turn: Turn): Direction {
val currentIndex = directionsInRightTurnOrder.indexOf(heading)
var nextIndex = currentIndex + if (turn == Turn.R) 1 else -1
if (nextIndex >= directionsInRightTurnOrder.size)
nextIndex = directionsInRightTurnOrder.size - nextIndex
if (nextIndex < 0)
nextIndex += directionsInRightTurnOrder.size
return directionsInRightTurnOrder.get(nextIndex)
}
However, this would be so much simpler and easier to read if I could take the directionsInRightTurnOrder list and cycle through it infinitely (and lazily). In Clojure, I can do that, using clojure.core/cycle:
(take 5 (cycle ["a" "b"]))
# ("a" "b" "a" "b" "a")
Another thing that would help is if I could look up in a list using a negative index, like in Ruby or Python:
http://rubyquicktips.com/post/996814716/use-negative-array-indices
Negative index to Python list
Question:
Can I do cycle through a list/collection in Kotlin?
Is there an idiomatic way to do a negative-index-lookup in Kotlin?
Here's cycle:
fun <T : Any> cycle(vararg xs: T): Sequence<T> {
var i = 0
return generateSequence { xs[i++ % xs.size] }
}
cycle("a", "b").take(5).toList() // ["a", "b", "a", "b", "a"]
Here's how you could implement turn application:
enum class Turn(val step: Int) { L(-1), R(1) }
enum class Direction {
N, E, S, W;
fun turned(turn: Turn): Direction {
val mod: (Int, Int) -> Int = { n, d -> ((n % d) + d) % d }
return values()[mod(values().indexOf(this) + turn.step, values().size)]
}
}
Sounds like modulo is what you're looking for -- negative index wrap-around. Couldn't find it in Kotlin's stdlib so I brought my own.
Direction.N
.turned(Turn.R) // E
.turned(Turn.R) // S
.turned(Turn.R) // W
.turned(Turn.R) // N
.turned(Turn.L) // W
Enum#values() and Enum#valueOf(_) are what let you access an enum's members programmatically.
Custom sequence, which repeats indefinitely the given sequence or list can be written quite easily in terms of flatten:
fun <T> Sequence<T>.repeatIndefinitely(): Sequence<T> =
generateSequence(this) { this }.flatten()
fun <T> List<T>.repeatIndefinitely(): Sequence<T> =
this.asSequence().repeatIndefinitely()
You can cycle through a list/collection in Kotlin by generating a sequence that returns the list/collection repeatedly and then flattening it. e.g.:
generateSequence { listOf("a", "b") }.flatten().take(5).toList()
// [a, b, a, b, a]
You can define your own modulo function for coercing both negative and positive numbers to valid indices to access elements in a list (see also Google Guava's IntMath.mod(int, int)):
infix fun Int.modulo(modulus: Int): Int {
if (modulus <= 0) throw ArithmeticException("modulus $modulus must be > 0")
val remainder = this % modulus
return if (remainder >= 0) remainder else remainder + modulus
}
val list = listOf("a", "b", "c", "d")
list[-1 modulo list.size] // last element
list[-2 modulo list.size] // second to last element
list[+9 modulo list.size] // second element
list[-12 modulo list.size] // first element
Paraphrasing the discussion on kotlin Slack:
using List#modulo would make this simpler, but not as elegant as cycle still, since negative indexes will still need to be handled.
One option to implement a cyclical list is a Sequence. However, a custom Sequence will need to be written, or generated using generateSequence. We thought it's an overkill for this situation.
Eventually I went with:
Making Direction aware of next and previous:
enum class Direction {
N, E, S, W;
private val order by lazy { listOf(N, E, S, W) }
fun add(turns: Int): Direction {
val currentIndex = order.indexOf(this)
var nextIndex = (currentIndex + turns) % order.size
return order.possiblyNegativeLookup(nextIndex)
}
fun subtract(turns: Int) = add(-1 * turns)
fun next(): Direction = add(1)
fun previous(): Direction = subtract(1)
}
Extending List with possiblyNegativeLookup:
fun <E> List<E>.possiblyNegativeLookup(i: Int): E {
return if (i < 0) this[this.size + i] else this[i]
}
So the final code turns into:
val nextHeading = if (move.turn == Turn.R) heading.next() else heading.previous()
I have a list of elements and I want to remove one of them, by value. In Python this would be
l = ["apples", "oranges", "melon"]
l.remove("melon")
print(l) # ["apples", "orange"]
What is the equivalent in Go? I found a slice trick to remove an element by index, but it's not very readable, still requires me to find the index manually and only works for a single item type:
func remove(l []string, item string) {
for i, other := range l {
if other == item {
return append(l[:i], l[i+1:]...)
}
}
}
There's the list.List structure, but it's not generic and thus requires tons of type-castings to use.
What is the idiomatic way of removing an element from a list?
The idiomatic way to remove an element from a list is to loop through it exactly like you do in your example. Removing an element by value from a slice shouldn't be too common in your program since it is an O(n) operation and there are better data structures in the language for that. Therefore, Go does not provide a built-in remove function for slices.
If you find yourself using removal by value often, consider using a set instead where removing and adding an element is O(1) while still being iterable.
set := map[string]bool{"apples":true, "oranges":true, "melon":true}
delete(set,"melon") // is O(1)
In generic Go (1.18) the filter function works on any comparable type. It removes only the first occurrence of the item.
func remove[T comparable](l []T, item T) []T {
for i, other := range l {
if other == item {
return append(l[:i], l[i+1:]...)
}
}
return l
}
Playground: https://go.dev/play/p/ojlYkvf5dQG?v=gotip
If you want to remove all occurrences, append the items that don't match to a new slice:
func remove[T comparable](l []T, item T) []T {
out := make([]T, 0)
for _, element := range l {
if element != item {
out = append(out, element)
}
}
return out
}
Playground: https://go.dev/play/p/W2MerNbh72H
If the slice items aren't comparable, you can use a custom equality function to filter:
func main() {
list := [][]int{{1, 2}, {2, 2}, {1, 10}}
newlist := remove(list, func(element []int) bool { return element[0] == 1 })
fmt.Println(newlist)
}
func remove[T any](l []T, remove func(T) bool) []T {
out := make([]T, 0)
for _, element := range l {
if !remove(element) {
out = append(out, element)
}
}
return out
}
Playground: https://go.dev/play/p/qZWoFbM_RUl