有没有一种简单的方法从数组中删除项目?

时间:2012-06-03 02:31:33

标签: c

我有两个清单。

char *name[] =  {"RGS", "O", "NRGY", "SIG", "BML-O", "BHI", "KSU", "ORN"};
char *name_to_remove[] =  {"RGS", "O", "NRGY"};

是否有一种有效的方法来获取项目列表并将其从其他列表中删除?我已经实现了自己的版本,但我觉得它效率很低。它基本上制作了名单的副本,然后使用了一个嵌套的for循环,它遍历了重复的名称和name_to_remove列出并标记任何重复“删除”的项目。最后,我浏览列表并复制除了值为'remove'的项目以外的所有项目。它非常丑陋,我怀疑效率低下。我遇到问题(之前没有处理过)的问题是我不确定如果数组在内存中是固定大小的话,是否有可能从数组中删除项目,所以我最初试图更改值,然后将值添加到一个新数组(与原始数据相同的大小 - 我要删除的项目数组的大小)。

我看不到更好的方法,memcmp看起来很有希望,因为它可以比较两个列表,但我无法弄清楚它是如何适合的。我知道C不是python,但这是我在python中干净利落的方式:

for item in name_to_remove:
    name_copy.remove(item)
也许在幕后,python命令正在做我正在做的循环,但我想我会问。

6 个答案:

答案 0 :(得分:2)

答案是使用适当的数据结构。 Python列表绝对不是作为普通的C字符串数组实现的(只是因为你可以在Python列表中存储不同类型的对象)。因此,您要查找的数据结构可能是linked listhash table

答案 1 :(得分:1)

  

它基本上制作了名单的副本,然后使用了一个嵌套的for循环,该循环遍历了重复的名称和& name_to_remove列出并标记重复到"删除"的任何项目。最后,我浏览列表并复制除了值为'删除'。

之外的所有项目

您可以只复制name中找到的{em> not 中的任何项目,而不是标记任何内容,并将其存储在新数组中,然后将其删除旧的name_to_remove数组。

答案 2 :(得分:1)

如果字符串的顺序无关紧要,您可以对两个数组进行排序以查找重复项,如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ARR_SIZE(array) sizeof(array)/sizeof(const char *)

int compare (const void * a, const void * b) {
    return strcmp(*((const char**)a), *((const char**)b));
}

int main(void) {
    const char *name[] =  {"RGS", "O", "NRGY", "SIG", "BML-O", "BHI", "KSU", "ORN"};
    const char *name_to_remove[] =  {"RGS", "O", "NRGY"};
    int i = 0, j = 0;
    qsort(name, ARR_SIZE(name), sizeof(const char*), compare);
    qsort(name_to_remove, ARR_SIZE(name_to_remove), sizeof(const char*), compare);
    while (i != ARR_SIZE(name) && j != ARR_SIZE(name_to_remove)) {
            int diff = strcmp(name[i], name_to_remove[j]);
            if (diff == 0) {
                    name[i] = NULL;
                    i++;
                    j++;
            } else if (diff < 0) {
                    i++;
            } else {
                    j++;
            }
    }
    for (i = 0 ; i != ARR_SIZE(name) ; i++)
            if (name[i])
                    printf("%s\n", name[i]);
    return 0;
}

答案 3 :(得分:0)

你可以制作一个哈希映射,然后遍历一个数组并通过mapOfRemovableWords.contains(words[i])进行测试并使用它来决定是否应该将元素复制到一个新数组(或者它自己的前面)。

您也可以对两个数组进行排序,然后同时迭代它们。使用这样的事实:如果您处于一个单词大于另一个单词中当前单词的位置,那么它不在另一个列表中。你迭代一个,然后决定是否需要迭代另一个,然后重复,直到你完全通过两者。

答案 4 :(得分:0)

我认为python版本的效率并不比你的代码高得多。

那就是说,你当然可以改善你的实施。记住,C数组实际上只是一个内存块,带有一串指向字符串开头的指针。由于您没有创建新字符串,因此您始终可以重用字符串指针。

从概念上讲,遍历数组,如果值在要删除的列表中,则将指针设置为null。然后使用malloc()创建适当大小的新数组。循环遍历旧数组,将非空指针复制到新数组。

这样你就有了2个循环迭代和一个malloc。

答案 5 :(得分:0)

如果在编译时分配第一个数组,那么它的大小是固定的,我相信随后通过“删除”所选元素来回收任何内存是不可能的。我建议实现一个你可以动态分配的链表,以及随后free()部分你希望删除一个项目,或者更好的是,一个更有效的数据结构,如二叉搜索树。< / p>