Can someone explain inserting into a slice with copy?

xuanbao · · 501 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;m having trouble understanding how to use <code>copy</code> for replacing elements in a slice.</p> <p>Playground: <a href="http://play.golang.org/p/MvzP3dQBDq">http://play.golang.org/p/MvzP3dQBDq</a></p> <p>Specifically, it&#39;s <code>copy(s[i+1:], s[i:])</code> which I can&#39;t make sense of. To me this says, &#34;copy the slice from i onwards into the slice of i+i onwards&#34;. To me that seems like it wouldn&#39;t modify the original slice at all.</p> <p>What&#39;s a better way to think about this?</p> <hr/>**评论:**<br/><br/>RalphCorderoy: <pre><p>It doesn&#39;t modify the original slice, but the memory backing the original slice. A slice is just a description, (pointer, len, capacity), of a chunk of that backing memory. You are giving two descriptions to <code>copy</code> that happen to be pointing to the same backing memory. As <a href="https://golang.org/ref/spec#Appending_and_copying_slices" rel="nofollow">https://golang.org/ref/spec#Appending_and_copying_slices</a> says, they are allowed to overlap and it copies the minimum of the two lens. Your <code>copy(s[i+1:], s[i:])</code> is pushing the run of elements from i+1 forward one element, leaving duplicates at s[i] and s[i+1].</p></pre>TheMerovius: <pre><blockquote> <p>What&#39;s a better way to think about this?</p> </blockquote> <p>What is the problem with thinking about it exactly this way? Because that&#39;s exactly what is happening, it copies all the elements from s[i:] to s[i+1:], which effectively means, it moves them all up one element (to make slot i free to insert the new one). With a couple more elements this is more easily visible: <a href="http://play.golang.org/p/86FVKcZdha" rel="nofollow">http://play.golang.org/p/86FVKcZdha</a></p> <p>Perhaps your confusion is between slices and arrays? i.e. that a slice doesn&#39;t really carry it&#39;s own memory, but that it&#39;s only a view into an array and that the &#34;elements&#34; of a slice are really the elements of the array it points to. So s[i:] and s[i+1:] really point to the same underlying array (which is the same as s). Thus, copying the elements from s[i+1:] to s[i:] moves the elements of the underlying array up one slot, starting from i.</p> <p>By the way, I don&#39;t know what the intended effect of your code is, but if it was supposed to be an insert, i.e. changing []int{0,1,2,3} to []int{0,1,8,2,3}, it&#39;s slightly incorrect, as there is a slot missing. You need to do something like this: <a href="http://play.golang.org/p/ugnvSktSOM" rel="nofollow">http://play.golang.org/p/ugnvSktSOM</a></p></pre>Perhyte: <pre><p>In your last example, you can also fold the copy into the append by appending the end of the slice to the beginning (with a little overlap). This is shorter and ensures that the append doesn&#39;t copy the whole slice (if the capacity was full) only to have the subsequent copy immediately overwrite large parts of it if inserting near the start. See <a href="https://play.golang.org/p/bUJdNpKIeB" rel="nofollow">https://play.golang.org/p/bUJdNpKIeB</a></p></pre>TheMerovius: <pre><p>I thought about that too, but preferred cleaner and more understandable code. As OP is apparently a beginner with go and slices in particular, I didn&#39;t want to mix too many concepts in and instead illustrate the basics. :)</p></pre>tgulacsi: <pre><p>copy is just an optimized cycle for copying the elements from the source slice onto the destination slice:</p> <p>for j := i; j &lt; len(s); j++ { s[i+1 + j] = s[j] }</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

501 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传