An implementation of bool slice based on byte array

blov · · 416 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>View boolslice on <a href="https://github.com/mkideal/pkg/blob/master/container/boolslice/boolslice.go" rel="nofollow">github</a></p> <pre><code>package boolslice type BoolSlice struct { data []byte length int } func New() *BoolSlice { return &amp;BoolSlice{data: []byte{}} } func NewWithSize(size, cap int) *BoolSlice { return &amp;BoolSlice{data: make([]byte, (size+7)&gt;&gt;3, (cap+7)&gt;&gt;3), length: size} } func NewWithSlice(slice []bool) *BoolSlice { size := len(slice) s := NewWithSize(size, size) for i := 0; i &lt; size; i++ { s.Set(i, slice[i]) } return s } func (s *BoolSlice) ij(index int) (i int, j byte) { return index &gt;&gt; 3, byte(index &amp; 0x7) } func (s *BoolSlice) Get(index int) bool { i, j := s.ij(index) return s.data[i]&amp;(1&lt;&lt;j) != 0 } func (s *BoolSlice) Set(index int, value bool) { i, j := s.ij(index) if value { s.data[i] |= 1 &lt;&lt; j } else { s.data[i] &amp;= ^(1 &lt;&lt; j) } } func (s *BoolSlice) Push(value bool) { i, j := s.ij(s.length) if i &gt;= len(s.data) { s.data = append(s.data, 0) } if value { s.data[i] |= 1 &lt;&lt; j } else { s.data[i] &amp;= ^(1 &lt;&lt; j) } s.length++ } func (s *BoolSlice) Pop() (value bool) { if s.length == 0 { panic(&#34;length == 0&#34;) } s.length-- value = s.Get(s.length) if n := (s.length &gt;&gt; 3) + 1; n &lt; len(s.data) { s.data = s.data[:n] } return } func (s *BoolSlice) Insert(index int, value bool) { s.Push(value) for i := s.length - 1; i &gt; index; i-- { s.Set(i, s.Get(i-1)) } s.Set(index, value) } func (s *BoolSlice) Truncate(from, to int) { if to &lt; s.length { s.length = to if n := (s.length &gt;&gt; 3) + 1; n &lt; len(s.data) { s.data = s.data[:n] } } if from &gt; 0 { l := to - from for i := 0; i &lt; l; i++ { s.Set(i, s.Get(i+from)) } s.length = l if n := (s.length &gt;&gt; 3) + 1; n &lt; len(s.data) { s.data = s.data[:n] } } } func (s *BoolSlice) Clone() *BoolSlice { s2 := &amp;BoolSlice{data: make([]byte, s.length), length: s.length} copy(s2.data, s.data) return s2 } func (s *BoolSlice) Equal(s2 *BoolSlice) bool { if s.length != s2.length { return false } for i, n := 0, len(s.data); i &lt; n; i++ { if s.data[i] != s2.data[i] { return false } } return true } func (s *BoolSlice) EqualToSlice(s2 []bool) bool { if s.Len() != len(s2) { return false } for i, n := 0, s.Len(); i &lt; n; i++ { if s.Get(i) != s2[i] { return false } } return true } </code></pre> <hr/>**评论:**<br/><br/>allhatenocattle: <pre><p>could you make this without the length field and just use length(data) when you need it? </p> <p>For Pop() I wouldn&#39;t panic, but might return 2 values like a get from a map, where first field is the value, 2nd is if there was an entry found.</p></pre>tucnak: <pre><p>So you made a bitset?</p></pre>tadvi: <pre><p>It seems that only 4 bools per one byte? Why not make it 8 bools per byte?</p></pre>ChristophBerger: <pre><p>It&#39;s difficult to see but the code does store 8 bools per byte.</p> <p><code>func ij()</code> returns two values:</p> <pre><code>i := index &gt;&gt; 3 </code></pre> <p>This is the same as index/8, to turn bit index into byte index.</p> <pre><code>j := byte(index &amp; 0x7) </code></pre> <p>This masks all but the lowest three bits (0x7 is 0b111). These are the bits that were lost in the <code>index &gt;&gt; 3</code>operation. They repesent a value between 0 and 7, which is the index of the bit within the i-th byte.</p></pre>

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

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