如何删除structs C数组中的重复值

如何删除structs C数组中的重复值,c,struct,C,Struct,我有一个按ID排序的结构数组,数组中有重复的ID条目。数组中的每个结构都有许多与其关联的点,我想找到每个ID的总点数。我想删除任何重复项,并将它们的总点数值存储在单个结构中,以减小数组的大小 typedef struct boat_data { int ID; int time_to_complete_race; //This can be ignored int points; } boat_node; typedef boat_node boat_ptr; 我所编写

我有一个按ID排序的结构数组,数组中有重复的ID条目。数组中的每个结构都有许多与其关联的点,我想找到每个ID的总点数。我想删除任何重复项,并将它们的总点数值存储在单个结构中,以减小数组的大小

typedef struct boat_data {
    int ID;
    int time_to_complete_race; //This can be ignored
    int points;
} boat_node;
typedef boat_node boat_ptr;
我所编写的当前代码似乎无法按预期工作。tot_Boots是指船只的数量,tot_members是指通过此方法找到的成员数量,我指的是存在的非重复ID的数量。我有两个数组结构,其中最终的_boat_分数是当前成员数的大小,我想存储ID值和points值


请让我知道您是否可以更改数组输入。如果是,那么每次需要将新元素存储到数组中时,您不能只检查ID吗?如果ID与已经存储的元素匹配,只需让recordedPoint+=point,即将要存储的点直接添加到数组上记录的总点中。这样您就不会创建重复的条目

编辑:由于无法更改输入数组,因此可以循环浏览boat_分数数组和final_boat_分数数组,并检查当前船只的ID是否已记录到final_boat_分数数组中。如果是,只需将其添加到总分中即可。我认为代码的问题在于没有循环遍历数组中的所有元素,因为数组的大小肯定不是total_-tot_成员。您也不需要最终的船分数[boat].ID=boat船分数[next船].ID;行,因为它是冗余的,所以if语句只在其为真时执行。 你的休息;语句也会过早地结束循环,在这种情况下,您不能提前脱离循环,因为您不知道有多少个条目具有相同的ID,对吗

//remember to initialize final_boat_score first with all IDs you have
for (int i = 0; i < final_boat_score_size; i++) {
    //initialize the total point = 0 first
    final_boat_score[i].points = 0;
    //then loop through your input data
    for (int j = 0; j < boat_score_size; i++) {
        //if there exist an input element boat_score[j] with the same ID
        //as the current final_boat_score[i] element, add its points to the total
        if (final_boat_score[i].ID == boat_score[j].ID) {
            final_boat_score[i].points += boat_score[j].points;
        }
    }
}


但这不会删除原始阵列,因此如果不再需要,您需要自己删除它。我希望这有帮助

请告诉我您是否可以更改数组输入。如果是,那么每次需要将新元素存储到数组中时,您不能只检查ID吗?如果ID与已经存储的元素匹配,只需让recordedPoint+=point,即将要存储的点直接添加到数组上记录的总点中。这样您就不会创建重复的条目

编辑:由于无法更改输入数组,因此可以循环浏览boat_分数数组和final_boat_分数数组,并检查当前船只的ID是否已记录到final_boat_分数数组中。如果是,只需将其添加到总分中即可。我认为代码的问题在于没有循环遍历数组中的所有元素,因为数组的大小肯定不是total_-tot_成员。您也不需要最终的船分数[boat].ID=boat船分数[next船].ID;行,因为它是冗余的,所以if语句只在其为真时执行。 你的休息;语句也会过早地结束循环,在这种情况下,您不能提前脱离循环,因为您不知道有多少个条目具有相同的ID,对吗

//remember to initialize final_boat_score first with all IDs you have
for (int i = 0; i < final_boat_score_size; i++) {
    //initialize the total point = 0 first
    final_boat_score[i].points = 0;
    //then loop through your input data
    for (int j = 0; j < boat_score_size; i++) {
        //if there exist an input element boat_score[j] with the same ID
        //as the current final_boat_score[i] element, add its points to the total
        if (final_boat_score[i].ID == boat_score[j].ID) {
            final_boat_score[i].points += boat_score[j].points;
        }
    }
}


但这不会删除原始阵列,因此如果不再需要,您需要自己删除它。我希望这有帮助

越来越多的数据使得排序和删除重复项变得越来越不可行,尽管这可能需要一段时间。一种是描述一个由id决定相等的集合,它是一种非常常见的数据结构;例如,在中,id将是您的密钥。该集合不允许每次都进行重复消除,而是首先不允许重复。A是一个散列集,实现为从键(在本例中为ID)到指示键存在的sentinel值的散列映射,任何char或int都可以。A在中有一个非常好的C实现,它创建了一个最小的完美散列,但我相信您希望有动态内容,这将转化为允许其他竞争对手加入俱乐部

由于一个键是一个数字,因此从投影创建哈希函数相当容易

int hash(const struct boat_data *const b) {
    return b->ID;
}
许多语言在其标准库中都支持哈希映射,例如,您的问题,但C不支持。然而,我们会发现很多实现。见a。另外,使用void*键,使用字符串

如果ID是有界的,并且在可计算性范围内,那么创建一个非最小函数很简单

#include <stdlib.h> /* EXIT */
#include <stdio.h>  /* printf */

static unsigned points_by_id[1000];
static size_t id_size = sizeof points_by_id / sizeof *points_by_id;

int main(void) {
    size_t i;
    /* First race between [45 36, 10]. */
    points_by_id[45] += 45;
    points_by_id[36] += 20;
    points_by_id[10] += 100;
    /* Second race between [10, 12, 45] */
    points_by_id[10] += 31;
    points_by_id[12] += 40;
    points_by_id[45] += 30;
    /* Print out. */
    printf("Total stadings:\n");
    for(i = 0; i < id_size; i++) {
        if(points_by_id[i])
            printf("%lu\t%u\n", (unsigned long)i, points_by_id[i]);
    }
    return EXIT_SUCCESS;
}

越来越多的数据使得排序和删除重复项变得越来越不可行,尽管这可能需要一段时间。一种是描述一个由id决定相等的集合,它是一种非常常见的数据结构;例如,在中,id将是您的密钥。该集合不允许每次都进行重复消除,而是首先不允许重复。A是一个散列集,实现为从键(在本例中为ID)到指示存在的sentinel值的散列映射 键,任何字符或int都可以。A在中有一个非常好的C实现,它创建了一个最小的完美散列,但我相信您希望有动态内容,这将转化为允许其他竞争对手加入俱乐部

由于一个键是一个数字,因此从投影创建哈希函数相当容易

int hash(const struct boat_data *const b) {
    return b->ID;
}
许多语言在其标准库中都支持哈希映射,例如,您的问题,但C不支持。然而,我们会发现很多实现。见a。另外,使用void*键,使用字符串

如果ID是有界的,并且在可计算性范围内,那么创建一个非最小函数很简单

#include <stdlib.h> /* EXIT */
#include <stdio.h>  /* printf */

static unsigned points_by_id[1000];
static size_t id_size = sizeof points_by_id / sizeof *points_by_id;

int main(void) {
    size_t i;
    /* First race between [45 36, 10]. */
    points_by_id[45] += 45;
    points_by_id[36] += 20;
    points_by_id[10] += 100;
    /* Second race between [10, 12, 45] */
    points_by_id[10] += 31;
    points_by_id[12] += 40;
    points_by_id[45] += 30;
    /* Print out. */
    printf("Total stadings:\n");
    for(i = 0; i < id_size; i++) {
        if(points_by_id[i])
            printf("%lu\t%u\n", (unsigned long)i, points_by_id[i]);
    }
    return EXIT_SUCCESS;
}


你在做什么有点不清楚。如果要从数组中删除某个元素,则需要将所有元素移过左一个元素。所以要从[1,2,3,4,5,6]中去掉3,向左移动4,5,6,它就变成了[1,2,4,5,6,6]。注意额外的6。这就是你想做的吗?你是在用malloc分配数组吗?id是一个很好的标志,表明一个人应该首先使用散列集并避免存储重复项。@Neil你能链接到一篇关于如何在C中实现这一点的文章吗?它与答案@stanle posted正交,占用了太多空间,所以我认为这可能值得一个答案。你在做什么有点不清楚。如果要从数组中删除某个元素,则需要将所有元素移过左一个元素。所以要从[1,2,3,4,5,6]中去掉3,向左移动4,5,6,它就变成了[1,2,4,5,6,6]。注意额外的6。这就是你想做的吗?你是在用malloc分配数组吗?id是一个很好的标志,表明人们应该首先使用散列集并避免存储重复项。@Neil你能链接到一篇关于如何在C中实现这一点的文章吗?它与答案@stanle posted正交,占用了太多空间,所以我认为这可能值得回答。这是一条评论,没有答案。请把它变成一个评论。@PaulOgilvie他不能。不,很遗憾,我不能改变它input@stanle这很好,但我不知道如何将我的所有ID添加到最终的_boat_score[]中,因为它们存储在另一个结构中。不用担心,我已经知道了如何操作谢谢!!这是评论,不是回答。请把它变成一个评论。@PaulOgilvie他不能。不,很遗憾,我不能改变它input@stanle这很好,但我不知道如何将我的所有ID添加到最终的_boat_score[]中,因为它们存储在另一个结构中。不用担心,我已经知道了如何操作谢谢!!C中似乎没有简单易用、正确且通用的哈希集,所以我使用创建了。C中似乎没有简单易用、正确且通用的哈希集,所以我使用创建了。