用于匹配文本名称的数据结构

时间:2012-10-15 21:48:51

标签: java python string-matching information-retrieval

我想找到文本文件中引用的名称。作者可以拥有任意数量的名称和标题。只有在所有名称都匹配时才会找到匹配项(例如,名为“John Doe”的人在仅包含“John”的文本中不匹配

我现在解决它的方法是将名称拆分为标记,并将第一个标记存储在HashSet中,并将小写字符串作为键。每个令牌都包含一组名称中的下一个标记,依此类推。

这会导致很多HashSet对象增加开销。我认为有更好的方法来处理这个问题?如果可能,我更喜欢图书馆,但任何事情都会有所帮助

如果那里有好的解决方案,我愿意切换到Python。

2 个答案:

答案 0 :(得分:0)

你能用正则表达式吗?根据文本文件的不同,您可能需要使用多行匹配,如下所示。

    Pattern p = Pattern.compile("John\\s+Doe", Pattern.MULTILINE);
    Matcher m = p.matcher("I am looking for John \nDoe, I am.");        
    System.out.println(m.find());

您也可以使用命令行实用程序pcregrep执行此操作 - 请参阅此related question

更新:为了解决存储名称的问题,用于存储相关字符串的内存高效结构是Trie,可能有用 - 可能有很多免费实现虽然据我所知,Java标准库中没有一个。另请参阅this question以及this one以获取一些建议。

答案 1 :(得分:0)

据我了解您的问题,您必须为每位作者存储任意名称列表,并有效地匹配它们。

我假设您已经解决了解析名称,删除非必要/可选部分(如'Dr')以及保留像'von'和'de'这样的粒子的问题。您的规范化名称必须是固定大小写的字符串序列(小写是正常的,但我坚持使用大写或标题大小写)。

现在,List<String>String[]可用作包含其他详细信息的HashMap的密钥。这样做不会很好,我担心,因为两者都是可变的,我不确定他们的hashCode()方法是否适合这种情况。

所以我想出了类似的东西:

class AuthorName(object) {
  private String[] parts;
  public AuthorName(String... name_parts) {
    assert name_parts.length > 0;
    parts = name_parts;
  }

  @Override
  public int hashCode() {
    // hashCode() that only depends on name parts
    int result = 0;
    for (int i=0; i < parts.length; i+=1) result ^= part.hashCode();
    return result;
  }
}

Map<AuthorName, ...> authors = new HashMap<AuthorName, ...>();
authors.put(new AuthorName('John', 'Doe'), ...);
assert authors.get(new AuthorName('John', 'Doe')) != 0

这并没有解决许多可能的问题,例如'Joe Random User','Joe R User'和'J. R.用户'是同一个人。这应该在不同的层面上解决。

如果您更详细地陈述您的案例,只需一两个例子,答案可能会更好。

您可能还对库规范化作者姓名的方式感兴趣。人们使用elaborate schemes来匹配名称。