我有两个清单。
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命令正在做我正在做的循环,但我想我会问。
答案 0 :(得分:2)
答案是使用适当的数据结构。 Python列表绝对不是作为普通的C字符串数组实现的(只是因为你可以在Python列表中存储不同类型的对象)。因此,您要查找的数据结构可能是linked list或hash 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>