1
0
mirror of https://github.com/rancher/os.git synced 2025-08-02 07:24:28 +00:00

slices union and intersection

useful for merging and splitting configs
This commit is contained in:
Ivan Mikushin 2015-08-21 13:24:55 +05:00
parent 974206235d
commit 4d6530be73
3 changed files with 146 additions and 56 deletions

View File

@ -10,55 +10,6 @@ import (
"strings"
)
func TestNilMap(t *testing.T) {
assert := require.New(t)
var m map[string]interface{} = nil
assert.True(m == nil)
}
func TestMapCopy(t *testing.T) {
assert := require.New(t)
m0 := map[interface{}]interface{}{"a": 1, "b": map[interface{}]interface{}{"c": 3}, "d": "4"}
m1 := util.MapCopy(m0)
delete(m0, "a")
assert.Equal(len(m1), len(m0)+1)
b0 := m0["b"].(map[interface{}]interface{})
b1 := m1["b"].(map[interface{}]interface{})
b1["e"] = "queer"
assert.Equal(len(b1), len(b0)+1)
}
func TestMapsIntersection(t *testing.T) {
assert := require.New(t)
m0 := map[interface{}]interface{}{"a": 1, "b": map[interface{}]interface{}{"c": 3}, "d": "4"}
m1 := util.MapCopy(m0)
delete(m0, "a")
b1 := m1["b"].(map[interface{}]interface{})
delete(b1, "c")
expected := map[interface{}]interface{}{"b": map[interface{}]interface{}{}, "d": "4"}
assert.Equal(expected, util.MapsIntersection(m0, m1, util.Equal))
}
func TestMapsUnion(t *testing.T) {
assert := require.New(t)
m0 := map[interface{}]interface{}{"a": 1, "b": map[interface{}]interface{}{"c": 3}, "d": "4"}
m1 := util.MapCopy(m0)
m1["e"] = "added"
m1["d"] = "replaced"
delete(m0, "a")
b1 := m1["b"].(map[interface{}]interface{})
delete(b1, "c")
expected := map[interface{}]interface{}{"a": 1, "b": map[interface{}]interface{}{"c": 3}, "d": "replaced", "e": "added"}
assert.Equal(expected, util.MapsUnion(m0, m1, util.Replace))
}
func TestFilterKey(t *testing.T) {
assert := require.New(t)
data := map[interface{}]interface{}{

View File

@ -181,6 +181,8 @@ func Copy(d interface{}) interface{} {
switch d := d.(type) {
case map[interface{}]interface{}:
return MapCopy(d)
case []interface{}:
return SliceCopy(d)
default:
return d
}
@ -197,11 +199,40 @@ func Equal(l, r interface{}) interface{} {
return nil
}
func ExistsIn(x interface{}, s []interface{}) bool {
for _, y := range s {
if reflect.DeepEqual(x, y) {
return true
}
}
return false
}
func SlicesUnion(left, right []interface{}, op func(interface{}, interface{}) interface{}) []interface{} {
result := SliceCopy(left)
for _, r := range right {
if !ExistsIn(r, result) {
result = append(result, r)
}
}
return result
}
func SlicesIntersection(left, right []interface{}, op func(interface{}, interface{}) interface{}) []interface{} {
result := []interface{}{}
for _, r := range right {
if ExistsIn(r, left) {
result = append(result, r)
}
}
return result
}
func MapsUnion(left, right map[interface{}]interface{}, op func(interface{}, interface{}) interface{}) map[interface{}]interface{} {
result := MapCopy(left)
for k, r := range right {
if l, ok := result[k]; ok {
if l, ok := left[k]; ok {
switch l := l.(type) {
case map[interface{}]interface{}:
switch r := r.(type) {
@ -210,6 +241,13 @@ func MapsUnion(left, right map[interface{}]interface{}, op func(interface{}, int
default:
result[k] = op(l, r)
}
case []interface{}:
switch r := r.(type) {
case []interface{}:
result[k] = SlicesUnion(l, r, op)
default:
result[k] = op(l, r)
}
default:
result[k] = op(l, r)
}
@ -226,19 +264,28 @@ func MapsIntersection(left, right map[interface{}]interface{}, op func(interface
for k, l := range left {
if r, ok := right[k]; ok {
switch r := r.(type) {
switch l := l.(type) {
case map[interface{}]interface{}:
switch l := l.(type) {
switch r := r.(type) {
case map[interface{}]interface{}:
result[k] = MapsIntersection(l, r, op)
default:
if i := op(l, r); i != nil {
result[k] = i
if v := op(l, r); v != nil {
result[k] = v
}
}
case []interface{}:
switch r := r.(type) {
case []interface{}:
result[k] = SlicesIntersection(l, r, op)
default:
if v := op(l, r); v != nil {
result[k] = v
}
}
default:
if i := op(l, r); i != nil {
result[k] = i
if v := op(l, r); v != nil {
result[k] = v
}
}
}
@ -255,6 +302,14 @@ func MapCopy(data map[interface{}]interface{}) map[interface{}]interface{} {
return result
}
func SliceCopy(data []interface{}) []interface{} {
result := make([]interface{}, len(data), len(data))
for k, v := range data {
result[k] = Copy(v)
}
return result
}
func GetServices(urls []string) ([]string, error) {
result := []string{}

View File

@ -6,6 +6,90 @@ import (
"testing"
)
func TestNilMap(t *testing.T) {
assert := require.New(t)
var m map[string]interface{} = nil
assert.True(m == nil)
}
func TestMapCopy(t *testing.T) {
assert := require.New(t)
m0 := map[interface{}]interface{}{"a": 1, "b": map[interface{}]interface{}{"c": 3}, "d": "4"}
m1 := MapCopy(m0)
assert.Equal(m0, m1)
delete(m0, "a")
assert.Equal(len(m1), len(m0)+1)
b0 := m0["b"].(map[interface{}]interface{})
b1 := m1["b"].(map[interface{}]interface{})
b1["e"] = "queer"
assert.Equal(len(b1), len(b0)+1)
}
func TestSliceCopy(t *testing.T) {
assert := require.New(t)
m0 := []interface{}{1, map[interface{}]interface{}{"c": 3}, "4"}
m1 := SliceCopy(m0)
assert.Equal(m0, m1)
m0 = m0[1:]
assert.Equal(len(m1), len(m0)+1)
b0 := m0[0].(map[interface{}]interface{})
b1 := m1[1].(map[interface{}]interface{})
b1["e"] = "queer"
assert.Equal(len(b1), len(b0)+1)
}
func TestMapsIntersection(t *testing.T) {
assert := require.New(t)
m0 := map[interface{}]interface{}{
"a": 1,
"b": map[interface{}]interface{}{"c": 3},
"d": "4",
"e": []interface{}{1, 2, 3},
}
m1 := MapCopy(m0)
delete(m0, "a")
b1 := m1["b"].(map[interface{}]interface{})
delete(b1, "c")
m1["e"] = []interface{}{2, 3, 4}
expected := map[interface{}]interface{}{"b": map[interface{}]interface{}{}, "d": "4", "e": []interface{}{2, 3}}
assert.Equal(expected, MapsIntersection(m0, m1, Equal))
}
func TestMapsUnion(t *testing.T) {
assert := require.New(t)
m0 := map[interface{}]interface{}{
"a": 1,
"b": map[interface{}]interface{}{"c": 3},
"d": "4",
"f": []interface{}{1, 2, 3},
}
m1 := MapCopy(m0)
m1["e"] = "added"
m1["d"] = "replaced"
m1["f"] = []interface{}{2, 3, 4}
delete(m0, "a")
b1 := m1["b"].(map[interface{}]interface{})
delete(b1, "c")
expected := map[interface{}]interface{}{
"a": 1,
"b": map[interface{}]interface{}{"c": 3},
"d": "replaced",
"e": "added",
"f": []interface{}{1, 2, 3, 4},
}
assert.Equal(expected, MapsUnion(m0, m1, Replace))
}
func TestLoadResourceSimple(t *testing.T) {
assert := require.New(t)