Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group by key + merge array values

Tags:

go

I'm trying to merge the array values of multiple arrays with same keys (sort of group by + merge). Is there any native way in Go to transform this input:

input = [
    [
        { a: 1, b: [1,2]},
        { a: 2, b: [1,2]},
        { a: 3, b: [1,2]}
    ],
    [
        { a: 1, b: [3,4]},
        { a: 2, b: [3,4]},
        { a: 3, b: [3,4]},
        { a: 4, b: [3,4]}
    ],
    [
        { a:1, b: [5,6]},
        { a:2, b: [5,6]},
        { a:3, b: [5,6]},
        { a:4, b: [5,6]},
        { a:5, b: [5,6]}
    ]
 ]

into:

output = [
    { a: 1, b: [1,2,3,4,5,6]},
    { a: 2, b: [1,2,3,4,5,6]},
    { a: 3, b: [1,2,3,4,5,6]},
    { a: 4, b: [3,4, 5,6]},
    { a: 5, b: [5,6]},
]
like image 464
inalgnu Avatar asked Oct 15 '16 22:10

inalgnu


1 Answers

Your code isn't Go code (it would pass as Ruby), which, along with no clear attempt on your part to actually solve the problem, is probably why you got some downvotes and no answers yet.

One approach would be to interpret your code as Ruby would, with input a slice of slices of maps of (string, maybe, although Ruby would treat them as Symbols) keys to either ints (in the case of a) or slices of ints (in the case of b). You could do that with the map values using the empty interface (interface{}), but it would be more straightforward to use a struct like this:

type ab struct {
    a int
    b []int
}

and have input be a [][]ab. But as long as we're restructuring your data to fit the language better, it's even more straightforward to do away with a and b altogether, replacing that structure with a map where the a values are the keys and the b values are the values. Things are then a simple matter of iterating over input and appending slices into output:

package main

import "fmt"

func main() {
    input := []map[int][]int{
        {
            1: []int{1, 2},
            2: []int{1, 2},
            3: []int{1, 2},
        },
        {
            1: []int{3, 4},
            2: []int{3, 4},
            3: []int{3, 4},
            4: []int{3, 4},
        },
        {
            1: []int{5, 6},
            2: []int{5, 6},
            3: []int{5, 6},
            4: []int{5, 6},
            5: []int{5, 6},
        },
    }

    output := make(map[int][]int)

    for _, m := range input {
        for k, v := range m {
            output[k] = append(output[k], v...)
        }
    }

    fmt.Println(output)
}

This produces the output:

map[1:[1 2 3 4 5 6] 2:[1 2 3 4 5 6] 3:[1 2 3 4 5 6] 4:[3 4 5 6] 5:[5 6]]

output thus has the data organized as you wanted, given the modified way of representing that data organization.

like image 63
Darshan Rivka Whittle Avatar answered Nov 13 '22 19:11

Darshan Rivka Whittle