Skip to content

Commit

Permalink
Keys+Values: accept multiple maps (vaargs) - Adding UniqKeys+UniqValu…
Browse files Browse the repository at this point in the history
…es (#503)

* added Keys: accept multiple maps (vaargs)

* added test:review comment fix

* added sort before asserting :review comment fix

* added sort before asserting :review comment fix

* output unique keys

* added map functions"

* added map_test.go and README.md

* added anchor in README.md

* added breakline in README.md

* fix README.md

* fix README.md and added test

* fix comments

* fix comments

* fix comments

* fix comments

* fix comments

* Update README.md

* small typo

* Update README.md

* Update README.md

* Update map.go

* Update map_test.go

---------

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
  • Loading branch information
shivamrazorpay and samber authored Jul 29, 2024
1 parent cb150f5 commit d8e5707
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 13 deletions.
53 changes: 51 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,11 @@ Supported helpers for slices:
Supported helpers for maps:

- [Keys](#keys)
- [HasKey](#HasKey)
- [UniqKeys](#uniqkeys)
- [HasKey](#haskey)
- [ValueOr](#valueor)
- [Values](#values)
- [UniqValues](#uniqvalues)
- [PickBy](#pickby)
- [PickByKeys](#pickbykeys)
- [PickByValues](#pickbyvalues)
Expand Down Expand Up @@ -1040,15 +1042,37 @@ result = lo.Splice([]string{"a", "b"}, 42, "1", "2")

### Keys

Creates an array of the map keys.
Creates a slice of the map keys.

Use the UniqKeys variant to deduplicate common keys.

```go
keys := lo.Keys(map[string]int{"foo": 1, "bar": 2})
// []string{"foo", "bar"}

keys := lo.Keys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3})
// []string{"foo", "bar", "baz"}

keys := lo.Keys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"bar": 3})
// []string{"foo", "bar", "bar"}
```

[[play](https://go.dev/play/p/Uu11fHASqrU)]

### UniqKeys

Creates an array of unique map keys.

```go
keys := lo.Keys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3})
// []string{"foo", "bar", "baz"}

keys := lo.Keys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"bar": 3})
// []string{"foo", "bar"}
```

[[play](https://go.dev/play/p/TPKAb6ILdHk)]

### HasKey

Returns whether the given key exists.
Expand All @@ -1067,13 +1091,38 @@ exists := lo.HasKey(map[string]int{"foo": 1, "bar": 2}, "baz")

Creates an array of the map values.

Use the UniqValues variant to deduplicate common values.

```go
values := lo.Values(map[string]int{"foo": 1, "bar": 2})
// []int{1, 2}

values := lo.Values(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3})
// []int{1, 2, 3}

values := lo.Values(map[string]int{"foo": 1, "bar": 2}, map[string]int{"bar": 2})
// []int{1, 2, 2}
```

[[play](https://go.dev/play/p/nnRTQkzQfF6)]

### UniqValues

Creates an array of unique map values.

```go
values := lo.UniqValues(map[string]int{"foo": 1, "bar": 2})
// []int{1, 2}

values := lo.UniqValues(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3})
// []int{1, 2, 3}

values := lo.UniqValues(map[string]int{"foo": 1, "bar": 2}, map[string]int{"bar": 2})
// []int{1, 2}
```

[[play](https://go.dev/play/p/nf6bXMh7rM3)]

### ValueOr

Returns the value of the given key or the fallback value if the key is not present.
Expand Down
57 changes: 50 additions & 7 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,32 @@ package lo

// Keys creates an array of the map keys.
// Play: https://go.dev/play/p/Uu11fHASqrU
func Keys[K comparable, V any](in map[K]V) []K {
result := make([]K, 0, len(in))
func Keys[K comparable, V any](in ...map[K]V) []K {
result := make([]K, 0)

for k := range in {
result = append(result, k)
for i := range in {
for k := range in[i] {
result = append(result, k)
}
}

return result
}

// UniqKeys creates an array of unique keys in the map.
// Play: https://go.dev/play/p/TPKAb6ILdHk
func UniqKeys[K comparable, V any](in ...map[K]V) []K {
seen := make(map[K]struct{})
result := make([]K, 0)

for i := range in {
for k := range in[i] {
if _, exists := seen[k]; exists {
continue
}
seen[k] = struct{}{}
result = append(result, k)
}
}

return result
Expand All @@ -21,11 +42,33 @@ func HasKey[K comparable, V any](in map[K]V, key K) bool {

// Values creates an array of the map values.
// Play: https://go.dev/play/p/nnRTQkzQfF6
func Values[K comparable, V any](in map[K]V) []V {
func Values[K comparable, V any](in ...map[K]V) []V {
result := make([]V, 0, len(in))

for k := range in {
result = append(result, in[k])
for i := range in {
for k := range in[i] {
result = append(result, in[i][k])
}
}

return result
}

// UniqValues creates an array of unique values in the map.
// Play: https://go.dev/play/p/nf6bXMh7rM3
func UniqValues[K comparable, V comparable](in ...map[K]V) []V {
seen := make(map[V]struct{})
result := make([]V, 0)

for i := range in {
for k := range in[i] {
val := in[i][k]
if _, exists := seen[val]; exists {
continue
}
seen[val] = struct{}{}
result = append(result, val)
}
}

return result
Expand Down
32 changes: 28 additions & 4 deletions map_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,44 @@ import (

func ExampleKeys() {
kv := map[string]int{"foo": 1, "bar": 2}
kv2 := map[string]int{"baz": 3}

result := Keys(kv)
result := Keys(kv, kv2)
sort.Strings(result)
fmt.Printf("%v", result)
// Output: [bar baz foo]

sort.StringSlice(result).Sort()
}

func ExampleUniqKeys() {
kv := map[string]int{"foo": 1, "bar": 2}
kv2 := map[string]int{"bar": 3}

result := UniqKeys(kv, kv2)
sort.Strings(result)
fmt.Printf("%v", result)
// Output: [bar foo]

}

func ExampleValues() {
kv := map[string]int{"foo": 1, "bar": 2}
kv2 := map[string]int{"baz": 3}

result := Values(kv, kv2)

sort.Ints(result)
fmt.Printf("%v", result)
// Output: [1 2 3]
}

func ExampleUniqValues() {
kv := map[string]int{"foo": 1, "bar": 2}
kv2 := map[string]int{"baz": 2}

result := Values(kv)
result := UniqValues(kv, kv2)

sort.IntSlice(result).Sort()
sort.Ints(result)
fmt.Printf("%v", result)
// Output: [1 2]
}
Expand Down
76 changes: 76 additions & 0 deletions map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,44 @@ func TestKeys(t *testing.T) {

r1 := Keys(map[string]int{"foo": 1, "bar": 2})
sort.Strings(r1)
is.Equal(r1, []string{"bar", "foo"})

r2 := Keys(map[string]int{})
is.Empty(r2)

r3 := Keys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3})
sort.Strings(r3)
is.Equal(r3, []string{"bar", "baz", "foo"})

r4 := Keys[string, int]()
is.Equal(r4, []string{})

r5 := Keys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"bar": 3})
sort.Strings(r5)
is.Equal(r5, []string{"bar", "bar", "foo"})
}

func TestUniqKeys(t *testing.T) {
t.Parallel()
is := assert.New(t)

r1 := UniqKeys(map[string]int{"foo": 1, "bar": 2})
sort.Strings(r1)
is.Equal(r1, []string{"bar", "foo"})

r2 := UniqKeys(map[string]int{})
is.Empty(r2)

r3 := UniqKeys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3})
sort.Strings(r3)
is.Equal(r3, []string{"bar", "baz", "foo"})

r4 := UniqKeys[string, int]()
is.Equal(r4, []string{})

r5 := UniqKeys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"foo": 1, "bar": 3})
sort.Strings(r5)
is.Equal(r5, []string{"bar", "foo"})
}

func TestHasKey(t *testing.T) {
Expand All @@ -36,8 +72,48 @@ func TestValues(t *testing.T) {

r1 := Values(map[string]int{"foo": 1, "bar": 2})
sort.Ints(r1)
is.Equal(r1, []int{1, 2})

r2 := Values(map[string]int{})
is.Empty(r2)

r3 := Values(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3})
sort.Ints(r3)
is.Equal(r3, []int{1, 2, 3})

r4 := Values[string, int]()
is.Equal(r4, []int{})

r5 := Values(map[string]int{"foo": 1, "bar": 2}, map[string]int{"foo": 1, "bar": 3})
sort.Ints(r5)
is.Equal(r5, []int{1, 1, 2, 3})
}

func TestUniqValues(t *testing.T) {
t.Parallel()
is := assert.New(t)

r1 := UniqValues(map[string]int{"foo": 1, "bar": 2})
sort.Ints(r1)
is.Equal(r1, []int{1, 2})

r2 := UniqValues(map[string]int{})
is.Empty(r2)

r3 := UniqValues(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3})
sort.Ints(r3)
is.Equal(r3, []int{1, 2, 3})

r4 := UniqValues[string, int]()
is.Equal(r4, []int{})

r5 := UniqValues(map[string]int{"foo": 1, "bar": 2}, map[string]int{"foo": 1, "bar": 3})
sort.Ints(r5)
is.Equal(r5, []int{1, 2, 3})

r6 := UniqValues(map[string]int{"foo": 1, "bar": 1}, map[string]int{"foo": 1, "bar": 3})
sort.Ints(r6)
is.Equal(r6, []int{1, 3})
}

func TestValueOr(t *testing.T) {
Expand Down

0 comments on commit d8e5707

Please sign in to comment.