C语言如何实现类似SQL的groupby分组?

99ANYc3cd6
预计阅读时长 18 分钟
位置: 首页 C语言 正文

在C语言中实现类似Python的groupby功能,通常需要手动处理数据分组逻辑,由于C语言本身没有内置的groupby函数,我们需要根据数据结构(如数组、链表等)和分组条件(如字段值、函数比较等)来实现。

c语言 groupby
(图片来源网络,侵删)

以下是几种实现groupby的常见方法:


方法1:基于数组的简单分组(适用于已排序数据)

如果数据已按分组键排序,可以遍历数组并按相同键的连续元素进行分组。

#include <stdio.h>
#include <string.h>
typedef struct {
    int id;
    char category[10];
    int value;
} Data;
// 打印分组结果
void print_group(const char *key, Data *group, int size) {
    printf("Group: %s\n", key);
    for (int i = 0; i < size; i++) {
        printf("  [%d, %s, %d]\n", group[i].id, group[i].category, group[i].value);
    }
}
// 分组函数(假设数据已按category排序)
void groupby(Data *data, int size) {
    if (size == 0) return;
    char current_key[10];
    int group_size = 0;
    Data current_group[size]; // 缓存当前分组(实际中应动态分配)
    strcpy(current_key, data[0].category);
    for (int i = 0; i < size; i++) {
        if (strcmp(data[i].category, current_key) == 0) {
            current_group[group_size++] = data[i];
        } else {
            // 打印当前分组
            print_group(current_key, current_group, group_size);
            // 开始新分组
            strcpy(current_key, data[i].category);
            group_size = 0;
            current_group[group_size++] = data[i];
        }
    }
    // 打印最后一个分组
    print_group(current_key, current_group, group_size);
}
int main() {
    Data data[] = {
        {1, "A", 10},
        {2, "A", 20},
        {3, "B", 30},
        {4, "B", 40},
        {5, "B", 50},
        {6, "C", 60}
    };
    int size = sizeof(data) / sizeof(data[0]);
    groupby(data, size);
    return 0;
}

输出:

Group: A
  [1, A, 10]
  [2, A, 20]
Group: B
  [3, B, 30]
  [4, B, 40]
  [5, B, 50]
Group: C
  [6, C, 60]

方法2:使用哈希表实现高效分组(适用于大数据量)

如果数据未排序或需要高效分组,可以用哈希表(如uthash库)存储分组。

c语言 groupby
(图片来源网络,侵删)

示例:使用uthash库

  1. 安装uthash(单头文件库):https://github.com/troydhanson/uthash
#include <stdio.h>
#include <string.h>
#include "uthash.h"
typedef struct {
    int id;
    char category[10];
    int value;
} Data;
typedef struct {
    char key[10];          // 分组键(如category)
    Data *items;           // 分组中的数据(动态数组)
    int count;             // 分组大小
    UT_hash_handle hh;     // uthash句柄
} Group;
Group *groups = NULL; // 全局哈希表
// 添加数据到分组
void add_to_group(Data *data) {
    Group *g;
    HASH_FIND_STR(groups, data->category, g);
    if (g == NULL) {
        g = malloc(sizeof(Group));
        strcpy(g->key, data->category);
        g->items = malloc(sizeof(Data) * 10); // 初始容量(需动态扩容)
        g->count = 0;
        HASH_ADD_STR(groups, key, g);
    }
    g->items[g->count++] = *data;
}
// 打印所有分组
void print_groups() {
    Group *g, *tmp;
    HASH_ITER(hh, groups, g, tmp) {
        printf("Group: %s\n", g->key);
        for (int i = 0; i < g->count; i++) {
            printf("  [%d, %s, %d]\n", g->items[i].id, g->items[i].category, g->items[i].value);
        }
        free(g->items);
        HASH_DEL(groups, g);
        free(g);
    }
}
int main() {
    Data data[] = {
        {1, "A", 10},
        {2, "A", 20},
        {3, "B", 30},
        {4, "B", 40},
        {5, "B", 50},
        {6, "C", 60}
    };
    int size = sizeof(data) / sizeof(data[0]);
    for (int i = 0; i < size; i++) {
        add_to_group(&data[i]);
    }
    print_groups();
    return 0;
}

输出与方法1相同,但支持未排序数据且效率更高。


方法3:自定义分组函数(灵活比较)

如果分组逻辑复杂(如按范围、函数比较等),可以封装一个通用的分组函数。

#include <stdio.h>
typedef struct {
    int value;
} Data;
// 自定义分组条件(示例:按value的奇偶性分组)
int group_key(Data *d) {
    return d->value % 2; // 0=偶数,1=奇数
}
void groupby(Data *data, int size, int (*key_func)(Data*)) {
    int group0[size], group1[size]; // 两个分组(实际中需动态分配)
    int count0 = 0, count1 = 0;
    for (int i = 0; i < size; i++) {
        if (key_func(&data[i]) == 0) {
            group0[count0++] = data[i].value;
        } else {
            group1[count1++] = data[i].value;
        }
    }
    printf("Even Group:\n");
    for (int i = 0; i < count0; i++) printf("%d ", group0[i]);
    printf("\n");
    printf("Odd Group:\n");
    for (int i = 0; i < count1; i++) printf("%d ", group1[i]);
    printf("\n");
}
int main() {
    Data data[] = {{1}, {2}, {3}, {4}, {5}, {6}};
    int size = sizeof(data) / sizeof(data[0]);
    groupby(data, size, group_key);
    return 0;
}

输出:

Even Group:
2 4 6 
Odd Group:
1 3 5 

  • 已排序数据:直接遍历分组(方法1)。
  • 未排序/大数据量:使用哈希表(如uthash,方法2)。
  • 复杂分组逻辑:自定义分组函数(方法3)。

根据实际需求选择合适的方法,注意内存管理和错误处理。

c语言 groupby
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
如何批量获取织梦站关键字?
« 上一篇 04-16
Elgamal加密在C语言中如何实现?
下一篇 » 04-16

相关文章

取消
微信二维码
支付宝二维码

目录[+]