Skip to content

Commit 8d48221

Browse files
authored
Merge pull request thoas#131 from yangtau/feat/to-set
feat: add ToSet()
2 parents 186887c + 11716cf commit 8d48221

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

README.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,33 @@ Transforms a slice of structs to a map based on a ``pivot`` field.
242242
243243
mapping := funk.ToMap(results, "ID") // map[int]*Foo{1: f, 2: b}
244244
245+
funk.ToSet
246+
..........
247+
248+
Transforms an array or a slice to a set (a map with zero-size values).
249+
250+
.. code-block:: go
251+
252+
f := Foo{
253+
ID: 1,
254+
FirstName: "Gilles",
255+
LastName: "Fabio",
256+
Age: 70,
257+
}
258+
259+
b := Foo{
260+
ID: 2,
261+
FirstName: "Florent",
262+
LastName: "Messa",
263+
Age: 80,
264+
}
265+
266+
mapping := funk.ToSet([]Foo{f, b}) // map[Foo]stuct{}{f: struct{}{}, b: struct{}{}}
267+
268+
mapping := funk.ToSet([4]int{1, 1, 2, 2}) // map[int]struct{}{1: struct{}{}, 2: struct{}{}}
269+
270+
271+
245272
funk.Filter
246273
...........
247274

transform.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,33 @@ func ToMap(in interface{}, pivot string) interface{} {
9898
return collection.Interface()
9999
}
100100

101+
// ToSet transforms a collection of instances to a Set.
102+
// []T => map[T]struct{}
103+
func ToSet(in interface{}) interface{} {
104+
// input value must be a collection
105+
if !IsCollection(in) {
106+
panic(fmt.Sprintf("%v must be a slice or an array", in))
107+
}
108+
109+
var (
110+
empty = struct{}{}
111+
emptyType = reflect.TypeOf(empty)
112+
emptyValue = reflect.ValueOf(empty)
113+
)
114+
115+
value := reflect.ValueOf(in)
116+
elemType := value.Type().Elem()
117+
118+
// key of the set will be the input type
119+
collection := reflect.MakeMap(reflect.MapOf(elemType, emptyType))
120+
121+
for i := 0; i < value.Len(); i++ {
122+
collection.SetMapIndex(value.Index(i), emptyValue)
123+
}
124+
125+
return collection.Interface()
126+
}
127+
101128
func mapSlice(arrValue reflect.Value, funcValue reflect.Value) reflect.Value {
102129
funcType := funcValue.Type()
103130

transform_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,50 @@ func TestToMap(t *testing.T) {
120120
}
121121
}
122122

123+
func TestToSet(t *testing.T) {
124+
is := assert.New(t)
125+
126+
type Foo struct {
127+
ID int
128+
Name string
129+
}
130+
131+
var (
132+
f1 = Foo{ID: 1, Name: "hello"}
133+
f2 = Foo{ID: 1, Name: "hello"}
134+
)
135+
136+
// [2]Foo -> map[Foo]struct{}
137+
array := [2]Foo{f1, f2}
138+
139+
resultOfArray := ToSet(array)
140+
is.True(reflect.TypeOf(resultOfArray).Kind() == reflect.Map)
141+
142+
setFromArray, ok := resultOfArray.(map[Foo]struct{})
143+
is.True(ok)
144+
is.True(len(setFromArray) == 1)
145+
146+
for k, v := range setFromArray {
147+
is.True(reflect.TypeOf(v).Size() == 0)
148+
is.True(k == f1)
149+
}
150+
151+
// []*Foo -> map[*Foo]struct{}
152+
slice := []*Foo{&f1, &f2, &f1, &f2}
153+
154+
resultOfSlice := ToSet(slice)
155+
is.True(reflect.TypeOf(resultOfSlice).Kind() == reflect.Map)
156+
157+
setFromSlice, ok := resultOfSlice.(map[*Foo]struct{})
158+
is.True(ok)
159+
is.True(len(setFromSlice) == 2)
160+
161+
for k, v := range setFromSlice {
162+
is.True(reflect.TypeOf(v).Size() == 0)
163+
is.True(k == &f1 || k == &f2)
164+
}
165+
}
166+
123167
func TestChunk(t *testing.T) {
124168
is := assert.New(t)
125169

0 commit comments

Comments
 (0)