Skip to content

Commit

Permalink
Merge branch 'oswaldom-code-feat-adding-chunk-map'
Browse files Browse the repository at this point in the history
  • Loading branch information
samber committed Jan 26, 2025
2 parents 6b110b3 + 4a03b54 commit 28a4d94
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 0 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,27 @@ mergedMaps := lo.Assign(

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

### ChunkEntries

Splits a map into an array of elements in groups of a length equal to its size. If the map cannot be split evenly, the final chunk will contain the remaining elements.

```go
maps := lo.ChunkEntries(
map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
},
3,
)
// []map[string]int{
// {"a": 1, "b": 2, "c": 3},
// {"d": 4, "e": 5},
// }
```

### MapKeys

Manipulates a map keys and transforms it to a map of another type.
Expand Down
40 changes: 40 additions & 0 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,46 @@ func Assign[K comparable, V any, Map ~map[K]V](maps ...Map) Map {
return out
}

// ChunkEntries splits a map into an array of elements in groups of a length equal to its size. If the map cannot be split evenly,
// the final chunk will contain the remaining elements.
func ChunkEntries[K comparable, V any](m map[K]V, size int) []map[K]V {
if size <= 0 {
panic("The chunk size must be greater than 0")
}

keys := make([]K, 0, len(m))
for key := range m {
keys = append(keys, key)
}

if len(keys) == 0 {
return []map[K]V{}
}

chunksNum := len(keys) / size
if len(keys)%size != 0 {
chunksNum += 1
}

result := make([]map[K]V, 0, chunksNum)

for i := 0; i < chunksNum; i++ {
start := i * size
end := (i + 1) * size
if end > len(keys) {
end = len(keys)
}

chunk := make(map[K]V)
for _, key := range keys[start:end] {
chunk[key] = m[key]
}
result = append(result, chunk)
}

return result
}

// MapKeys manipulates a map keys and transforms it to a map of another type.
// Play: https://go.dev/play/p/9_4WPIqOetJ
func MapKeys[K comparable, V any, R comparable](in map[K]V, iteratee func(value V, key K) R) map[R]V {
Expand Down
20 changes: 20 additions & 0 deletions map_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,26 @@ func ExampleAssign() {
// Output: 3 1 3 4
}

func ExampleChunkEntries() {
result := ChunkEntries(
map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
},
3,
)

for i := range result {
fmt.Printf("%d\n", len(result[i]))
}
// Output:
// 3
// 2
}

func ExampleMapKeys() {
kv := map[int]int{1: 1, 2: 2, 3: 3, 4: 4}

Expand Down
46 changes: 46 additions & 0 deletions map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,52 @@ func TestAssign(t *testing.T) {
is.IsType(after, before, "type preserved")
}

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

result1 := ChunkEntries(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, 2)
result2 := ChunkEntries(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, 3)
result3 := ChunkEntries(map[string]int{}, 2)
result4 := ChunkEntries(map[string]int{"a": 1}, 2)
result5 := ChunkEntries(map[string]int{"a": 1, "b": 2}, 1)

expectedCount1 := 3
expectedCount2 := 2
expectedCount3 := 0
expectedCount4 := 1
expectedCount5 := 2

is.Len(result1, expectedCount1)
is.Len(result2, expectedCount2)
is.Len(result3, expectedCount3)
is.Len(result4, expectedCount4)
is.Len(result5, expectedCount5)

is.PanicsWithValue("The chunk size must be greater than 0", func() {
ChunkEntries(map[string]int{"a": 1}, 0)
})
is.PanicsWithValue("The chunk size must be greater than 0", func() {
ChunkEntries(map[string]int{"a": 1}, -1)
})

type myStruct struct {
Name string
Value int
}

allStructs := []myStruct{{"one", 1}, {"two", 2}, {"three", 3}}
nonempty := ChunkEntries(map[string]myStruct{"a": allStructs[0], "b": allStructs[1], "c": allStructs[2]}, 2)
is.Len(nonempty, 2)

originalMap := map[string]int{"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}
result6 := ChunkEntries(originalMap, 2)
for k := range result6[0] {
result6[0][k] = 10
}
is.Equal(originalMap, map[string]int{"a": 1, "b": 2, "c": 3, "d": 4, "e": 5})
}

func TestMapKeys(t *testing.T) {
t.Parallel()
is := assert.New(t)
Expand Down

0 comments on commit 28a4d94

Please sign in to comment.