我需要在C中实现内存中的字符串元组匹配功能。将有大量的元组列表与不同的操作相关联,并且要与列表匹配大量事件。
元组列表:
("one", "four")
("one")
("three")
("four", "five")
("six")
事件(“一个”,“两个”,“三个”,“四个”)应匹配列表项(“一个”,“四个”)和(“一个”)和(“三个”)但不符合(“四个“,”五个“而不是(”六个“)
我当前的方法使用所有元组字段值的映射作为使用该值的每个元组的列表的键。有很多冗余哈希和列表插入。
有没有正确或经典的方法来做到这一点?
答案 0 :(得分:3)
如果你只有少量可能的元组值,那么编写某种散列函数是有意义的,它可以将它们变成整数索引以便快速搜索。
如果有<您可以使用位掩码执行32个值:
unsigned int hash(char *value){...}
typedef struct _tuple {
unsigned int bitvalues;
void * data
} tuple;
tuple a,b,c,d;
a.bitvalues = hash("one");
a.bitvalues |= hash("four");
//a.data = something;
unsigned int event = 0;
//foreach value in event;
event |= hash(string_val);
// foreach tuple
if(x->bitvalues & test == test)
{
//matches
}
如果有太多的值来执行位掩码解决方案,则可以使用一组链接列表。浏览活动中的每个项目。如果该项与key_one匹配,请使用该第一个键遍历元组并检查事件是否有第二个键:
typedef struct _tuple {
unsigned int key_one;
unsigned int key_two;
_tuple *next;
void * data;
} tuple;
tuple a,b,c,d;
a.key_one = hash("one");
a.key_two = hash("four");
tuple * list = malloc(/*big enough for all hash indexes*/
memset(/*clear list*/);
//foreach touple item
if(list[item->key_one])
put item on the end of the list;
else
list[item->key_one] = item;
//foreach event
//foreach key
if(item_ptr = list[key])
while(item_ptr.next)
if(!item_ptr.key_two || /*item has key_two*/)
//match
item_ptr = item_ptr.next;
此代码未经过测试,可能存在许多小错误,但您应该明白这一点。 (纠正的一个错误是元组匹配的测试条件)
如果事件处理速度至关重要,那么迭代所有构造的元组,计算出现次数并经历可能重新排序每个元组的一个/两个键的键是有意义的,这样最独特的值列出第一。
答案 1 :(得分:2)
一种可能的解决方案是为每个单词分配一个唯一的素数。
然后,如果将每个元组中的单词相乘,那么您有一个代表列表中单词的数字。
将一个列表除以另一个列表,如果得到整数余数,则另一个列表包含在另一个列表中。
答案 2 :(得分:1)
我不知道有任何经典或正确的方法,所以这就是我要做的事情:P
看起来你想使用set theory行话决定A是否是B的超集。你可以做的一种方法是对A和B进行排序,并对A和B进行合并排序操作,因为你试图找到B中A值的位置。 B中也属于A的那些元素将具有重复,而其他元素则不具有重复。因为A和B都是排序的,所以这不应该太可怕。
例如,你取B的第一个值,然后走A直到你在A中找到它的副本。然后取第二个B值,然后从你之前离开的地方开始走A.如果你在没有找到匹配的情况下结束A,那么A不是B的超集,你返回false。
如果这些元组可以保持排序,那么排序成本只会产生一次。
答案 3 :(得分:0)
如果您有少量可能的字符串,则可以为每个字符串分配索引并使用位图。这样一个简单的按位,会告诉你是否有重叠。
如果这不实用,那么您的反向索引设置可能很难与速度匹配,特别是如果您只需要构建一次。 (元组列表是否在运行时更改?)
答案 4 :(得分:0)
public static void Main()
{
List<List<string>> tuples = new List<List<string>>();
string [] tuple = {"one", "four"};
tuples.Add(new List<string>(tuple));
tuple = new string [] {"one"};
tuples.Add(new List<string>(tuple));
tuple = new string [] {"three"};
tuples.Add(new List<string>(tuple));
tuple = new string[]{"four", "five"};
tuples.Add(new List<string>(tuple));
tuple = new string[]{"six"};
tuples.Add(new List<string>(tuple));
tuple = new string[] {"one", "two", "three", "four"};
List<string> checkTuple = new List<string>(tuple);
List<List<string>> result = new List<List<string>>();
foreach (List<string> ls in tuples)
{
bool ok = true;
foreach(string s in ls)
if(!checkTuple.Contains(s))
{
ok = false;
break;
}
if (ok)
result.Add(ls);
}
}