🐿 Extend SortSliceByValue with more types

This commit is contained in:
Evgeniy Kulikov 2019-04-12 14:09:49 +03:00
parent 7462e26df6
commit e06640668d
No known key found for this signature in database
GPG key ID: BF6AEE0A2A699BF2
2 changed files with 122 additions and 13 deletions

57
hrw.go
View file

@ -86,22 +86,73 @@ func SortSliceByValue(slice interface{}, hash uint64) {
case int: case int:
var key = make([]byte, 16) var key = make([]byte, 16)
slice := slice.([]int) slice := slice.([]int)
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
binary.BigEndian.PutUint64(key, uint64(slice[i])) binary.BigEndian.PutUint64(key, uint64(slice[i]))
rule = append(rule, weight(Hash(key), hash)) rule = append(rule, weight(Hash(key), hash))
} }
case uint:
var key = make([]byte, 16)
slice := slice.([]uint)
for i := 0; i < length; i++ {
binary.BigEndian.PutUint64(key, uint64(slice[i]))
rule = append(rule, weight(Hash(key), hash))
}
case int8:
slice := slice.([]int8)
for i := 0; i < length; i++ {
key := byte(slice[i])
rule = append(rule, weight(Hash([]byte{key}), hash))
}
case uint8:
slice := slice.([]uint8)
for i := 0; i < length; i++ {
key := slice[i]
rule = append(rule, weight(Hash([]byte{key}), hash))
}
case int16:
var key = make([]byte, 8)
slice := slice.([]int16)
for i := 0; i < length; i++ {
binary.BigEndian.PutUint16(key, uint16(slice[i]))
rule = append(rule, weight(Hash(key), hash))
}
case uint16:
var key = make([]byte, 8)
slice := slice.([]uint16)
for i := 0; i < length; i++ {
binary.BigEndian.PutUint16(key, slice[i])
rule = append(rule, weight(Hash(key), hash))
}
case int32: case int32:
var key = make([]byte, 16) var key = make([]byte, 16)
slice := slice.([]int32) slice := slice.([]int32)
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
binary.BigEndian.PutUint32(key, uint32(slice[i])) binary.BigEndian.PutUint32(key, uint32(slice[i]))
rule = append(rule, weight(Hash(key), hash)) rule = append(rule, weight(Hash(key), hash))
} }
case uint32:
var key = make([]byte, 16)
slice := slice.([]uint32)
for i := 0; i < length; i++ {
binary.BigEndian.PutUint32(key, slice[i])
rule = append(rule, weight(Hash(key), hash))
}
case int64:
var key = make([]byte, 32)
slice := slice.([]int64)
for i := 0; i < length; i++ {
binary.BigEndian.PutUint64(key, uint64(slice[i]))
rule = append(rule, weight(Hash(key), hash))
}
case uint64:
var key = make([]byte, 32)
slice := slice.([]uint64)
for i := 0; i < length; i++ {
binary.BigEndian.PutUint64(key, slice[i])
rule = append(rule, weight(Hash(key), hash))
}
case string: case string:
slice := slice.([]string) slice := slice.([]string)
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
rule = append(rule, weight(hash, rule = append(rule, weight(hash,
Hash([]byte(slice[i])))) Hash([]byte(slice[i]))))

View file

@ -9,7 +9,14 @@ import (
"testing" "testing"
) )
type hashString string type (
hashString string
unknown byte
slices struct {
actual interface{}
expect interface{}
}
)
var testKey = []byte("0xff51afd7ed558ccd") var testKey = []byte("0xff51afd7ed558ccd")
@ -44,6 +51,7 @@ func Example() {
// trying GET six.example.com/examples/object-key // trying GET six.example.com/examples/object-key
// trying GET five.example.com/examples/object-key // trying GET five.example.com/examples/object-key
} }
func (h hashString) Hash() uint64 { func (h hashString) Hash() uint64 {
return Hash([]byte(h)) return Hash([]byte(h))
} }
@ -118,8 +126,8 @@ func TestSortSliceByValueFail(t *testing.T) {
}) })
t.Run("must 'fail' for unknown type", func(t *testing.T) { t.Run("must 'fail' for unknown type", func(t *testing.T) {
actual := []byte{1, 2, 3, 4, 5} actual := []unknown{1, 2, 3, 4, 5}
expect := []byte{1, 2, 3, 4, 5} expect := []unknown{1, 2, 3, 4, 5}
hash := Hash(testKey) hash := Hash(testKey)
SortSliceByValue(actual, hash) SortSliceByValue(actual, hash)
if !reflect.DeepEqual(actual, expect) { if !reflect.DeepEqual(actual, expect) {
@ -139,12 +147,64 @@ func TestSortSliceByValueHasher(t *testing.T) {
} }
func TestSortSliceByValueIntSlice(t *testing.T) { func TestSortSliceByValueIntSlice(t *testing.T) {
actual := []int{0, 1, 2, 3, 4, 5} cases := []slices{
expect := []int{2, 3, 1, 4, 0, 5} {
actual: []int{0, 1, 2, 3, 4, 5},
expect: []int{2, 3, 1, 4, 0, 5},
},
{
actual: []uint{0, 1, 2, 3, 4, 5},
expect: []uint{2, 3, 1, 4, 0, 5},
},
{
actual: []int8{0, 1, 2, 3, 4, 5},
expect: []int8{2, 0, 5, 1, 4, 3},
},
{
actual: []uint8{0, 1, 2, 3, 4, 5},
expect: []uint8{2, 0, 5, 1, 4, 3},
},
{
actual: []int16{0, 1, 2, 3, 4, 5},
expect: []int16{5, 4, 0, 3, 2, 1},
},
{
actual: []uint16{0, 1, 2, 3, 4, 5},
expect: []uint16{5, 4, 0, 3, 2, 1},
},
{
actual: []int32{0, 1, 2, 3, 4, 5},
expect: []int32{1, 3, 5, 4, 2, 0},
},
{
actual: []uint32{0, 1, 2, 3, 4, 5},
expect: []uint32{1, 3, 5, 4, 2, 0},
},
{
actual: []int64{0, 1, 2, 3, 4, 5},
expect: []int64{1, 5, 3, 4, 2, 0},
},
{
actual: []uint64{0, 1, 2, 3, 4, 5},
expect: []uint64{1, 5, 3, 4, 2, 0},
},
}
hash := Hash(testKey) hash := Hash(testKey)
SortSliceByValue(actual, hash)
if !reflect.DeepEqual(actual, expect) { for _, tc := range cases {
t.Errorf("Was %#v, but expected %#v", actual, expect) SortSliceByValue(tc.actual, hash)
if !reflect.DeepEqual(tc.actual, tc.expect) {
t.Errorf("Was %#v, but expected %#v", tc.actual, tc.expect)
}
} }
} }
@ -326,7 +386,6 @@ func TestUniformDistribution(t *testing.T) {
"Chi2 condition for .9 is not met (expected %.2f <= %.2f)", "Chi2 condition for .9 is not met (expected %.2f <= %.2f)",
chi2, chiTable[size-1]) chi2, chiTable[size-1])
} }
}) })
t.Run("sortByInt32Value", func(t *testing.T) { t.Run("sortByInt32Value", func(t *testing.T) {
@ -367,7 +426,6 @@ func TestUniformDistribution(t *testing.T) {
"Chi2 condition for .9 is not met (expected %.2f <= %.2f)", "Chi2 condition for .9 is not met (expected %.2f <= %.2f)",
chi2, chiTable[size-1]) chi2, chiTable[size-1])
} }
}) })
t.Run("hash collision", func(t *testing.T) { t.Run("hash collision", func(t *testing.T) {