0

i have this code

    type key struct {
        account  string
        quantity float64
    }
    type invoice_tag struct {
        account              string
        value_after_discount float64
        value                float64
        price                float64
        total_discount       float64
        discount             float64
        quantity             float64
    }

    invoice := []invoice_tag{{"Cash", 1024, 1024, 1, 0, 0, 1024}, {"Service Revenue", 0, 2048, 2, 0, 0, 1024}, {"Service Revenue", 0, 0, 0, 1024, 1, 1024}}
    m := map[key][5]float64{}
    for _, i := range invoice {
        m[key{i.account, i.quantity}] = [5]float64{i.value_after_discount, i.value, i.price, i.total_discount, i.discount}

    }
    fmt.Println(m)

i want to group by account and quantity and to sum value_after_discount with value_after_discount and value with value and price with price and total_discount with total_discount and discount with discount. and the output should be

map[{Cash 1024}:[1024 1024 1 0 0] {Service Revenue 1024}:[1024 2048 2 1024 1]]

https://play.golang.org/p/KKTmovpfN1z

icza
  • 389,944
  • 63
  • 907
  • 827
user17148257
  • 149
  • 2
  • 7
  • 1
    See [How to make composite key for a hash map in go](https://stackoverflow.com/questions/52348514/how-to-make-composite-key-for-a-hash-map-in-go/52348704#52348704) – icza Oct 28 '21 at 07:46
  • @icza ok but how to sum multiple values? – user17148257 Oct 28 '21 at 07:52
  • To sum `a` and `b` and `c`, you just write `a + b + c`. Please explain what it is you don't understand. – icza Oct 28 '21 at 07:54
  • @icza i mean i want to sum the `a` with the previous `a` and `b` with the previous `b` and `c` with the previous `c` that have the same keys – user17148257 Oct 28 '21 at 07:58
  • You store the sum in the map, and in the next iteration you read that value, add the new value and store the new sum back in the map. Something like: `mymap[key] += value`. – icza Oct 28 '21 at 08:25
  • @icza i mean i want to sum `value_after_discount` with `value_after_discount` and `value` with `value` and `price` with `price` and `total_discount` with `total_discount` and `discount` with `discount` and return like this `map[{Cash 1024}:[1024 1024 1 0 0] {Service Revenue 1024}:[1024 2048 2 1024 1]]` – user17148257 Oct 28 '21 at 08:35
  • Then do that. Use a struct which holds fields you want to sum. In each iteration read the previous struct from the map, calculate the sums (by fields), and store the new struct value back in the map. (Or alternatively you may store a pointer to that struct, so you don't need to store the new value, you just modify the pointed struct's fields.) – icza Oct 28 '21 at 08:42
  • @icza I don't know how to do it I am Beginner can you solved in the answer please. – user17148257 Oct 28 '21 at 08:49

1 Answers1

0

Use a struct as the composite key with account and quantity fields. Note: float number comparisons may surprise you, if quantity is an integer number, you should use an integer number (e.g. int)!

Use a struct that holds the values you want to sum. For simplicity, I'll use invoice_tag for this because it contains all the required fields, but you may create a separate struct too to your liking.

I'll store a pointer to this struct in the map, so when I update it in each iteration, I don't have to store the new value.

For example:

m := map[key]*invoice_tag{}
for _, i := range invoice {
    k := key{i.account, i.quantity}
    sums := m[k]
    if sums == nil {
        sums = &invoice_tag{}
        m[k] = sums
    }
    sums.value_after_discount += i.value_after_discount
    sums.value += i.value
    sums.price += i.price
    sums.total_discount += i.total_discount
    sums.discount += i.discount
}

for k, v := range m {
    fmt.Printf("key: %v, sums: value_after_discount: %f, value: %f, price: %f, total_discount: %f, discount: %f\n",
        k, v.value_after_discount, v.value, v.price, v.total_discount, v.discount)
}

This will output (try it on the Go Playground):

key: {Cash 1024}, sums: value_after_discount: 1024.000000, value: 1024.000000, price: 1.000000, total_discount: 0.000000, discount: 0.000000
key: {Service Revenue 1024}, sums: value_after_discount: 0.000000, value: 2048.000000, price: 2.000000, total_discount: 1024.000000, discount: 1.000000

Again: this works because the input data we used contains identical floating point constant literals (which result in identical float64 value). In practice the grouping may give incorrect results due to IEEE 754 floating point quirks. I recommend using int for quantity if possible. If not possible, then format the quantities to identical format (including certain digit rounding).

icza
  • 389,944
  • 63
  • 907
  • 827