When the slice element is removed, the original slice is broken - go
package main
import (
"fmt"
)
func main() {
// test data
var a = [][]int{
[]int{1,2},
[]int{3,4},
[]int{5,6},
[]int{7,8},
}
for i := range a {
fmt.Println(a) // print out
_ = append(a[:i], a[i+1:]...) // remove element
}
}
expected result
[[1 2] [3 4] [5 6] [7 8]]
[[1 2] [3 4] [5 6] [7 8]]
[[1 2] [3 4] [5 6] [7 8]]
[[1 2] [3 4] [5 6] [7 8]]
actual result
[[1 2] [3 4] [5 6] [7 8]]
[[3 4] [5 6] [7 8] [7 8]]
[[3 4] [7 8] [7 8] [7 8]]
[[3 4] [7 8] [7 8] [7 8]]
https://play.golang.org/p/KahcX1MmDHO
why does this result? the original slice is broken. :(
When you re-slice you don't change the underlying array. So the first time through your loop (append(a[:0], a[1:]...)) you create a[:0] which is a slice of len 0 (cap 4) pointing to the element 0 and a[1:] is a slice of len 3 (cap 3) pointing to element 1.
As #icza pointed out using append() in this way just moved the underlying array elements around. For each loop iteration this happens:
0: elements 1-3 are moved to places 0-2
1: elements 2-3 are moved to places 1-2
2: element 3 is moved to place 2
3: nothing is moved since a[4:] has zero length
This gives the changed values that you see.
BTW Please post the simplest code which shows the problem. The nested slice is irrelevant.
func main() {
var a = []int{1,2,3,4}
for i := range a {
fmt.Println(a)
_ = append(a[:i], a[i+1:]...)
}
}
Related
Golang slice append exception
This is a leet code problem, and when I try to answer with the code blew: package main import "fmt" func main() { nums := []int{9, 0, 3, 5, 7} fmt.Println(subsets(nums)) } func subsets(nums []int) [][]int { var result [][]int result = append(result, []int{}) for _, v := range(nums) { for _, rv := range(result) { result = append(result, append(rv, v)) } } return result } Leetcode told me wrong answer: Wrong Answer Details Input [9,0,3,5,7] Output [[],[9],[0],[9,0],[3],[9,3],[0,3],[9,0,3],[5],[9,5],[0,5],[9,0,5],[3,5],[9,3,5],[0,3,5],[9,0,3,7],[7],[9,7],[0,7],[9,0,7],[3,7],[9,3,7],[0,3,7],[9,0,3,7],[5,7],[9,5,7],[0,5,7],[9,0,5,7],[3,5,7],[9,3,5,7],[0,3,5,7],[9,0,3,7,7]] Expected [[],[9],[0],[0,9],[3],[3,9],[0,3],[0,3,9],[5],[5,9],[0,5],[0,5,9],[3,5],[3,5,9],[0,3,5],[0,3,5,9],[7],[7,9],[0,7],[0,7,9],[3,7],[3,7,9],[0,3,7],[0,3,7,9],[5,7],[5,7,9],[0,5,7],[0,5,7,9],[3,5,7],[3,5,7,9],[0,3,5,7],[0,3,5,7,9]] The output slice index 15, it should be [9,0,3,5] like the expected, but the result is [9,0,3,7]. So I try to run this code by go playgroud online,the answer is the same wrong, and then I run this code in goland with debug mode,I find when I make the slice append([9,0,3], 7), the output slice index 15 change at the same time. My local go env: go version go1.17.6 windows/amd64 I'm just a beginner to golang, could anyone explain this situation? Thank you very much. ps: I try to use blew code to recover same issue, but I failed. package main import "fmt" func main() { a := [][]int{{}, {9}, {0}, {9, 0}, {3}, {9, 3}, {0, 3}, {9, 0, 3}, {5}, {9, 5}, {0, 5}, {9, 0, 5}, {3, 5}, {9, 3, 5}, {0, 3, 5}, {9, 0, 3, 5}} i := 7 for _, v := range a { // fmt.Println(a) a = append(a, append(v, i)) // fmt.Println(a) } fmt.Println(a) } result: [[] [9] [0] [9 0] [3] [9 3] [0 3] [9 0 3] [5] [9 5] [0 5] [9 0 5] [3 5] [9 3 5] [0 3 5] [9 0 3 5] [7] [9 7] [0 7] [9 0 7] [3 7] [9 3 7] [0 3 7] [9 0 3 7] [5 7] [9 5 7] [0 5 7] [9 0 5 7] [3 5 7] [9 3 5 7] [0 3 5 7] [9 0 3 5 7]]
You are reusing the same backing array in some of your slices, because that's what append does if there's capacity remaining. A simple fix is to replace append(rv, v) with append(append([]int{}, rv...), v), creating an entirely new slice. An alternative is to force the append to allocate a fresh backing array by capping the slice to its current length: append(rv[:len(rv):len(rv)], v). Playground link with working code: https://go.dev/play/p/Gc-yF5KQOAO
How can you seed a first item with bufferWithCount in rx.js?
Say you do something like: Rx.Observable.range(1, 5).bufferWithCount(2, 1).subscribe(console.log); This returns: [1, 2] [2, 3] [3, 4] [4, 5] [5] I'd like for the result to look like (basically force the first value to emit): [<userDefined>, 1] [1, 2] [3, 4] etc...
How about: Rx.Observable.range(1, 5) // Note this value will get used for every subscription // after it is defined. .startWith(userDefined) .bufferWithCount(2, 1) .subscribe(console.log);
Update matrix in-place in Clojure
Suppose I have a Clojure matrix A as such (formatted for clarity) [[1 4 3] [1 7 3] [1 8 3]] Now suppose I want to update the first column in place, by e.g. multiplying it by a factor of two, so that the new matrix becomes [[2 4 3] [2 2 3] [2 8 3]] How would one do this in clojure? I have tried things like assoc and stuff like (join-along 1 (* (slice A 1 0) 2) (select A [0 1 2] [2 3])) Naturally that did not work. It would be great if there was something like assoc for matrices e.g. (massoc A [rows] [columns] replacement-vector) or something simple like numpy in Python: A[:,0]*2 = [[2 4 3] [2 2 3] [2 8 3]] Thanks
You should look into clojure.core/matrix and see if it supports operations like this. Here is something that may be what you're looking for. It should be trivial to change this to assoc a new value rather than updating after applying a function. (defn mupdate-in "Update all `coll' rows at `column' with `f'" [coll column f & args] (reduce #(apply update-in %1 [%2 column] f args) coll (range (count coll)))) An example: (def m [[1 4 3] [1 7 3] [1 8 3]]) (mupdate-in m 0 * 2) ;; [[2 4 3] ;; [2 7 3] ;; [2 8 3]] (mupdate-in m 2 + 10) ;; [[1 4 13] ;; [1 7 13] ;; [1 8 13]]
Adding rows / columns to existing matrices in core.matrix (Clojure)
How does one add a row or a column to an existing matrix? I'm trying to add a bias-term, a column of ones, as the first row of a matrix. In Octave I can do this with: M = [ones(size(M, 1), 1), M];
You can use the join function to append arrays along the major dimension. And you can combine this with broadcast to get a matrix of ones in whatever size you like, e.g.: e.g. (join (broadcast 1 [1 3]) [[1 2 3] [4 5 6] [7 8 9]]) => [[1 1 1] [1 2 3] [4 5 6] [7 8 9]]
How do I write Ruby's each_cons in Clojure?
How can I rewrite this Ruby code in Clojure? seq = [1, 2, 3, 4, 5].each_cons(2) #=> lazy Enumerable of pairs seq.to_a => [[1, 2], [2, 3], [3, 4], [4, 5]] Clojure: (??? 2 [1 2 3 4 5]) ;=> lazy seq of [1 2] [2 3] [3 4] [4 5]
What you are asking for is called sliding window over a lazy sequence.This way you can achieve that user=> (partition 2 1 [1 2 3 4 5]) ((1 2) (2 3) (3 4) (4 5))