用 Java 实现最佳匹配搜索

2024-03-30

我正在尝试使用现有的 Java 数据结构获得最佳匹配字符串匹配。虽然速度很慢,但任何提高其性能的建议都将受到欢迎。

样本数据看起来像这样

Key | V
--------------------- 
0060175559138 | VIP
--------------
006017555     | National
--------------
006017        | Local
---------------
0060          | X
--------------

因此,对键 = 0060175552020 进行最佳匹配搜索将返回 006017555

我能想到的一种方法是使用多个 TreeMap 使用散列将数据转移到不同的映射中,从而使搜索区域更小。

private final TreeMap<String, V> index;

public Set<V> syncBestMatch(String key) {              
    Entry<String,V> entry = index.headMap(key, true)
                .descendingMap().entrySet().stream()
                .filter(e -> isPartiallyOrFullyMatching(key, e.getKey()))
                .findFirst()
                .orElseThrow(() -> new NoMatchException("No match found"));

    Set<V> results = new HashSet<>();
    results.add(entry.getValue());
    return results;
}

Use a TreeMapfloorEntry(K key) https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html#floorEntry-K- method:

返回与小于或等于给定键的最大键关联的键值映射,或者null如果没有这样的密钥。

以下是简化的。如果发现无效条目,则实际代码需要搜索,例如如果地图有钥匙0060175551000,在这种情况下,您需要找到搜索键和找到的键之间的公共前缀,然后再次进行查找。冲洗并重复。

TreeMap<String, String> map = new TreeMap<>();
map.put("0060175559138", "VIP");
map.put("006017555"    , "National");
map.put("006017"       , "Local");
map.put("0060"         , "X");

String key = "0060175552020";
Entry<String, String> entry = map.floorEntry(key);
if (entry == null)
    System.out.println("Not found: " + key);
else {
    System.out.println(key);
    System.out.println(entry);
}

Output

0060175552020
006017555=National

UPDATE有完整的代码,带有用于扩展搜索的循环。

private static Entry<String, String> lookup(NavigableMap<String, String> map, String key) {
    String keyToFind = key;
    for (;;) {
        Entry<String, String> entry = map.floorEntry(keyToFind);
        if (entry == null)
            return null;
        String foundKey = entry.getKey();
        int prefixLen = 0;
        while (prefixLen < keyToFind.length() && prefixLen < foundKey.length() &&
               keyToFind.charAt(prefixLen) == foundKey.charAt(prefixLen))
            prefixLen++;
        if (prefixLen == 0)
            return null;
        if (prefixLen == foundKey.length())
            return entry;
        keyToFind = key.substring(0, prefixLen);
    }
}

Test

TreeMap<String, String> map = new TreeMap<>();
map.put("0060175559138", "VIP");
map.put("0060175551000", "Other");
map.put("006017555"    , "National");
map.put("006017"       , "Local");
map.put("0060"         , "X");

System.out.println(lookup(map, "0060175559138"));
System.out.println(lookup(map, "0060175552020"));
System.out.println(lookup(map, "0055708570068"));
System.out.println(lookup(map, "8684064893870"));

Output

0060175559138=VIP
006017555=National
null
null
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用 Java 实现最佳匹配搜索 的相关文章

随机推荐

  • BeautifulSoup:从锚标记中提取文本

    我想提取 来自以下 src 的文本image tag and 锚标记的文本位于div类数据 我成功地提取了 img src 但在从锚标记中提取文本时遇到了问题 a class title href http www amazon com N
  • 上传文件限制

    如何限制上传文件 例如 如果数据库已有 5 个条目 则不应采用第 6 个条目 并展示您只能拥有 5 个文件 我的代码
  • 如何在 MATLAB 中创建用于播放、暂停、快进和快退视频的 GUI?

    我是 MATLAB 新手 我正在尝试创建一个 GUI 来逐帧播放 暂停 快进和快退 avi 视频 目前 我可以通过切换按钮播放和暂停视频 但是当我再次按下播放时 视频从零帧开始播放 我意识到我需要存储下次按播放时使用的帧号 但我不知道该怎么
  • 为什么我会收到 InvalidDnDOperationException?

    I m sorry I don t like asking why am I getting exception questions on StackOverflow bit ironic now that I think of it bu
  • 存储指向堆栈值的指针(Golang)

    我正在尝试用 Go 进行实验 看看如果我将指向变量的指针存储在堆栈上 然后在原始变量离开作用域后访问该变量 会发生什么情况 package main import fmt var p chan bool a temp struct type
  • 错误:GDK_BACKEND 与可用显示器不匹配;使用 Crontab 运行 Selenium

    我正在尝试使用 cron 运行 selenium import os from selenium import webdriver from selenium webdriver firefox options import Options
  • 发送 HTML 电子邮件 asp

    我想在电子邮件中添加一些 html 我已经尝试过以下方法 vFromName someone vFromAddress someemail vTo recipient vSubject someSubject vBodyofemail ta
  • Client = Discord.client() TypeError: 'module' 对象不可调用

    为什么我会得到TypeError module object is not callable用我的代码 import discord from discord ext commands import Bot from discord ext
  • Google Cloud Endpoints:verifyToken:签名长度不正确

    今天早上 从我的 Android 应用程序向我的 Google Cloud Endpoint 发出的每个 API 请求都开始出现以下异常 com google api server spi auth GoogleIdTokenUtils v
  • 测量任务之间的响应时间

    我正在编写一个程序 用Python 它返回一些数据 我想知道如何测量请求和答案之间的响应时间 用于性能分析 然后我会将其存储在某个地方 有一种更好更有效的方法来做到这一点 或者只是插入例如time ctime 在请求和另一个请求之前time
  • 使用 TPL 时如何管理线程本地存储 (TLS)?

    我想将日志记录上下文信息存储在 TLS 中 以便可以在入口点设置一个值 并使该值在所有结果堆栈中可用 这工作得很好 但我还使用了 TPL 和 ThreadPool 那么问题就变成了如何将 TLS 数据迁移到其他线程 我可以自己完成这一切 但
  • 如何为具有大图像目录的博客设置 Jekyll,以避免在生成的站点中重复该目录?

    我正在考虑使用 Jekyll 构建一个网站 该网站将成为一个包含大量图像 以及其他大型媒体文件 的博客 创建图像目录 然后根据帖子中的需要链接到它们是很容易的 但是 据我了解 生成站点时 所有图像数据将被复制到保存静态文件的生成的 site
  • 如何在 IntelliJ IDEA 中搜索特定代码块?

    我如何搜索withinIntelliJ IDEA 中的特定代码块或选择 I got used to using this feature in Eclipse In Eclipse you can just double click on
  • 为什么 ViewModelProvider 在屏幕旋转时创建视图模型的新实例?

    我试图实现分页 但每次旋转视图模型的屏幕构造函数都会被调用 从而触发 loadInitial 从我的 DataSource 类中的网络获取新数据 感谢帮助 ViewModel def lifecycle version 2 2 0 impl
  • 有关新 Windows 10 错误的信息:ERROR_CLOUD_FILE_ACCESS_DENIED

    打开文件进行读取时遇到新的 Windows 10 错误代码CreateFile 我们得到错误395 但关于其含义或如何解决的信息很少 Windows 10 SDK的错误详细信息如下 错误编号395 误差常数ERROR CLOUD FILE
  • 获取中位数对应的索引

    我有一个带有一列的 pandas 数据框 我想知道中位数的索引 也就是说 我这样确定中位数 df 中位数 这给了我中值 但我想知道该行的索引 这个可以确定吗 对于长度不均匀的列表 我可以搜索具有该值的索引 但对于均匀的列表长度 这是行不通的
  • JSR303 自定义验证器被调用两次

    我正在使用 Spring MVC 创建一个网站 为了持久性 我使用 Spring Data JPA 和 Hibernate 4 作为我的 JPA 提供程序 目前正在使用 Hibernate Validator 处理验证 我遇到一个问题 我的
  • Javascript 嵌套函数失去作用域

    有人可以解释一下以下代码的范围绑定吗 window name window object name object method function nestedMethod function console log this name nes
  • 无法在 GitHub 上呈现标头

    这是我的README md在 GitHub 存储库中 This is a Header This is not a Header 这两行都呈现为纯文本 第一个应该呈现为标题 我记得它之前是这样的 我不知道我的浏览器 macOS 上的 Chr
  • 用 Java 实现最佳匹配搜索

    我正在尝试使用现有的 Java 数据结构获得最佳匹配字符串匹配 虽然速度很慢 但任何提高其性能的建议都将受到欢迎 样本数据看起来像这样 Key V 0060175559138 VIP 006017555 National 006017 Lo