Groups the given columns by the corresponding grouping column
    value, and aggregate by summing values.

    Args:
        columns (List<WeldObject>): List of columns as WeldObjects
        column_tys (List<str>): List of each column data ty
        grouping_column (WeldObject): Column to group rest of columns by

    Returns:
          A WeldObject representing this computation

def flatten_group(expr, column_tys, grouping_column_tys):
    """
    Groups the given columns by the corresponding grouping column
    value, and aggregate by summing values.

    Args:
        columns (List<WeldObject>): List of columns as WeldObjects
        column_tys (List<str>): List of each column data ty
        grouping_column (WeldObject): Column to group rest of columns by

    Returns:
          A WeldObject representing this computation
    """
    weld_obj = WeldObject(encoder_, decoder_)

    group_var = weld_obj.update(expr)

    num_group_cols = len(grouping_column_tys)
    if num_group_cols == 1:
        grouping_column_ty_str = "%s" % grouping_column_tys[0]
        grouping_column_key_str = "a.$0"
    else:
        grouping_column_tys = [str(ty) for ty in grouping_column_tys]
        grouping_column_ty_str = ", ".join(grouping_column_tys)
        grouping_column_ty_str = "{%s}" % grouping_column_ty_str
        grouping_column_keys = ["a.$0.$%s" % i for i in range(0, num_group_cols)]
        grouping_column_key_str = "{%s}" % ", ".join(grouping_column_keys)

    if len(column_tys) == 1:
        tys_str = "%s" % column_tys[0]
        column_values_str = "b.$1"
    else:
        column_tys = [str(ty) for ty in column_tys]

        tys_str = "{%s}" % ", ".join(column_tys)
        column_values = ["b.$%s" % i for i in range(0, len(column_tys))]
        column_values_str = "{%s}" % ", ".join(column_values)

    # TODO: The output in pandas keps the keys sorted (even if keys are structs)
    # We need to allow keyfunctions in sort by clauses to be able to compare structs.
    # sort(%(group_vec)s, |x:{%(gty)s, vec[%(ty)s]}| x.$0),
    weld_template = """
    flatten(
      map(
        %(group_vec)s,
        |a:{%(gty)s, vec[%(ty)s]}| map(a.$1, |b:%(ty)s| {%(gkeys)s, %(gvals)s})
      )
    )
  """

    weld_obj.weld_code = weld_template % {"group_vec": expr.weld_code,
                                          "gkeys": grouping_column_key_str,
                                          "gvals": column_values_str,
                                          "ty": tys_str,
                                          "gty": grouping_column_ty_str}
    return weld_obj