c - 检查结构元素并将其与 C 中的用户输入进行比较
问题描述
我正在尝试在 C 中创建一个函数,该函数在包含客户信息的数据库中进行搜索,将其与某些用户输入进行比较,并最终根据依赖于 Livenshtein 距离百分比的条件打印出良好的结果。
typedef struct Person_t
{
char Name[32];
char Email[64];
char City[96];
char Country[64];
} Person;
问题来了,要求用户输入结构成员所代表的每个信息,但他只能输入他想要的,例如:姓名:Emily,电子邮件:(没有用户输入,也就是留空),城市: (留空),国家:法国。
这里的目标是仅将这些属性(Emily,Country)与数据库中的相应属性进行比较,因为:正如我所说,比较算法基于与 Livenshtein 距离相关的条件,如果该条件不通过说 50,它不会将搜索验证为“好结果”,这可能会排除好的情况,比如:
姓名:杰克,电子邮件:jack.jack@gmail.com,城市:伯明翰,国家:美国
这个客户存在于我们的“大”数据库中(假设我们有很多 Jacks 和很多来自 Birmingham 的人),并且 smbd 正在搜索对 Jack 知之甚少的信息,因此他输入:
姓名:Jackk,电子邮件:(空),城市:(空),国家:美国
(我故意弄乱拼写以显示 LD 如何有用,它的百分比仍然很高,所以不用担心)
使用 LD 的百分比条件:百分比 = (1 - LD/max(string1, string2)) * 100,我们将截止设置为 50%。
这里的问题是,如果我们将每个结构成员与其对应的结构成员(与用户输入的内容相关的结构成员)进行比较,我们就会降低它获得高百分比的可能性,因为将空字符串与“现有”字符串进行比较将使 Livenshtein 距离很大,因此百分比很低,这将带走很多好的结果。
重要的是要注意,我不想使用OR。我不知道如果他得到正确的“杰克”,它将通过(百分比= 100),由于存在太多杰克(我们正在谈论一个大数据库),这将不会有效,所以我肯定会使用AND,以确保所有用户输入尽可能接近他想要的,同时尽量减少结果的数量。
请记住,除此之外,搜索后的结果将根据百分比进行排序,因此需要彻底按照该百分比处理空白字符串。
解决方案
这是我的评论的一个例子。
compare_field
如果存在有效匹配,则该函数返回 1 并填充percentage
out 参数;如果该字段无关紧要,则返回 0。
该compare_record
函数调用该函数 4 次,每个字段一次,并平均字段比较函数返回的百分比。
#include <stdio.h>
#include <string.h>
typedef struct Person_t {
char Name[32];
char Email[64];
char City[96];
char Country[64];
} Person;
static Person database[] = {
{.Name = "Emily",
.Email = "emi@x.ly",
.City = "Paris",
.Country = "France"},
{.Name = "Jack",
.Email = "jack.jack@gmail.com",
.City = "Birmingham",
.Country = "United States"},
{.Name = "Jank",
.Email = "jankjank@gmail.com",
.City = "London",
.Country = "United Kingdom"},
};
static int compare_field(const char *record, const char *query,
float *percentage) {
if (strlen(record) == 0 || strlen(query) == 0) {
return 0; // Ignore this field in the search
}
// TODO: implement real levenshtein distance here
int distance = 0;
for (int i = 0;; i++) {
if (record[i] == 0 || query[i] == 0)
break;
if (record[i] != query[i])
distance++;
}
*percentage = (1.0f - distance / (float)strlen(record)) * 100.0f;
return 1;
}
static float compare_record(const Person *record, const Person *query) {
float total_match_percentage = 0, temp_percentage;
int total_match_fields = 0;
#define COMPARE_FIELD(field) if (compare_field(record->field, query->field, &temp_percentage)) { total_match_percentage += temp_percentage; total_match_fields++; }
COMPARE_FIELD(Name);
COMPARE_FIELD(Email);
COMPARE_FIELD(City);
COMPARE_FIELD(Country);
#undef COMPARE_FIELD
return total_match_percentage / (float)total_match_fields;
}
int main() {
int n_database = sizeof(database) / sizeof(Person);
Person query = {.Name = "Jamk", .City = "Pondon", .Country = "United K"};
for (int i = 0; i < n_database; i++) {
float match = compare_record(&database[i], &query);
printf("%s: %.2f\n", database[i].Name, match);
}
}
在query
源代码中,这会打印出来(因为 Emily 仍然匹配P
aris 并且我没有实现完整的 Levenshtein 距离算法)......
Emily: 13.33
Jack: 72.44
Jank: 86.11
推荐阅读
- php - 在 Laravel 公共文件夹中安装 WordPress
- c++ - 如何计算 N 个排序集的交集?
- r - 合并具有相同列和行的两个数据框
- arrays - 如何将数组值插入到 Selenium IDE 中的 xpath 语法搜索中
- javascript - 在fabric js中动态再现背景
- javascript - 根据在另一个页面中输入的值更新表值的功能
- javascript - 监视模拟服务人员(msw)?
- bash - 如何组合多个 awk 命令并用空格打印
- r - 如何将一个字符列分成两列?
- javascript - 未能在“CustomElementRegistry”上执行“定义”: