Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9eb853bc authored by Colin Cross's avatar Colin Cross
Browse files

Add SortedStringValues and SortedUniqueStringValues

Add SortedStringValues and SortedUniqueStringValues that return the
values of a string-valued map.  Also make the SortedStringKeys
function use a similar implementation with MapRange, which avoids
iterating over the keys twice, once in MapKeys to build the list
of key reflect.Values and once over the reflect.Values to convert
them to strings.

Test: util_test.go
Change-Id: I4fc990a5036421e8926094ee158fafe606d0f10b
parent c2cdd8ab
Loading
Loading
Loading
Loading
+39 −5
Original line number Diff line number Diff line
@@ -65,21 +65,55 @@ func JoinWithSuffix(strs []string, suffix string, separator string) string {
	return buf.String()
}

// SorterStringKeys returns the keys of the given string-keyed map in the ascending order
// SorterStringKeys returns the keys of the given string-keyed map in the ascending order.
func SortedStringKeys(m interface{}) []string {
	v := reflect.ValueOf(m)
	if v.Kind() != reflect.Map {
		panic(fmt.Sprintf("%#v is not a map", m))
	}
	keys := v.MapKeys()
	s := make([]string, 0, len(keys))
	for _, key := range keys {
		s = append(s, key.String())
	if v.Len() == 0 {
		return nil
	}
	iter := v.MapRange()
	s := make([]string, 0, v.Len())
	for iter.Next() {
		s = append(s, iter.Key().String())
	}
	sort.Strings(s)
	return s
}

// stringValues returns the values of the given string-valued map in randomized map order.
func stringValues(m interface{}) []string {
	v := reflect.ValueOf(m)
	if v.Kind() != reflect.Map {
		panic(fmt.Sprintf("%#v is not a map", m))
	}
	if v.Len() == 0 {
		return nil
	}
	iter := v.MapRange()
	s := make([]string, 0, v.Len())
	for iter.Next() {
		s = append(s, iter.Value().String())
	}
	return s
}

// SortedStringValues returns the values of the given string-valued map in the ascending order.
func SortedStringValues(m interface{}) []string {
	s := stringValues(m)
	sort.Strings(s)
	return s
}

// SortedUniqueStringValues returns the values of the given string-valued map in the ascending order
// with duplicates removed.
func SortedUniqueStringValues(m interface{}) []string {
	s := stringValues(m)
	return SortedUniqueStrings(s)
}

// IndexList returns the index of the first occurrence of the given string in the list or -1
func IndexList(s string, list []string) int {
	for i, l := range list {
+114 −0
Original line number Diff line number Diff line
@@ -640,3 +640,117 @@ func BenchmarkFirstUniqueStrings(b *testing.B) {
		})
	}
}

func TestSortedStringKeys(t *testing.T) {
	testCases := []struct {
		name     string
		in       interface{}
		expected []string
	}{
		{
			name:     "nil",
			in:       map[string]string(nil),
			expected: nil,
		},
		{
			name:     "empty",
			in:       map[string]string{},
			expected: nil,
		},
		{
			name:     "simple",
			in:       map[string]string{"a": "foo", "b": "bar"},
			expected: []string{"a", "b"},
		},
		{
			name:     "interface values",
			in:       map[string]interface{}{"a": nil, "b": nil},
			expected: []string{"a", "b"},
		},
	}

	for _, tt := range testCases {
		t.Run(tt.name, func(t *testing.T) {
			got := SortedStringKeys(tt.in)
			if g, w := got, tt.expected; !reflect.DeepEqual(g, w) {
				t.Errorf("wanted %q, got %q", w, g)
			}
		})
	}
}

func TestSortedStringValues(t *testing.T) {
	testCases := []struct {
		name     string
		in       interface{}
		expected []string
	}{
		{
			name:     "nil",
			in:       map[string]string(nil),
			expected: nil,
		},
		{
			name:     "empty",
			in:       map[string]string{},
			expected: nil,
		},
		{
			name:     "simple",
			in:       map[string]string{"foo": "a", "bar": "b"},
			expected: []string{"a", "b"},
		},
		{
			name:     "duplicates",
			in:       map[string]string{"foo": "a", "bar": "b", "baz": "b"},
			expected: []string{"a", "b", "b"},
		},
	}

	for _, tt := range testCases {
		t.Run(tt.name, func(t *testing.T) {
			got := SortedStringValues(tt.in)
			if g, w := got, tt.expected; !reflect.DeepEqual(g, w) {
				t.Errorf("wanted %q, got %q", w, g)
			}
		})
	}
}

func TestSortedUniqueStringValues(t *testing.T) {
	testCases := []struct {
		name     string
		in       interface{}
		expected []string
	}{
		{
			name:     "nil",
			in:       map[string]string(nil),
			expected: nil,
		},
		{
			name:     "empty",
			in:       map[string]string{},
			expected: nil,
		},
		{
			name:     "simple",
			in:       map[string]string{"foo": "a", "bar": "b"},
			expected: []string{"a", "b"},
		},
		{
			name:     "duplicates",
			in:       map[string]string{"foo": "a", "bar": "b", "baz": "b"},
			expected: []string{"a", "b"},
		},
	}

	for _, tt := range testCases {
		t.Run(tt.name, func(t *testing.T) {
			got := SortedUniqueStringValues(tt.in)
			if g, w := got, tt.expected; !reflect.DeepEqual(g, w) {
				t.Errorf("wanted %q, got %q", w, g)
			}
		})
	}
}