terasum / js-mdict

*.mdx/*.mdd interpreter js implements, support mdict index file
MIT License
159 stars 18 forks source link

部分单词查询 不准确 #67

Open tonyzhou1890 opened 2 years ago

tonyzhou1890 commented 2 years ago

比如《新牛津英汉双解大词典》查询 word 的结果是 -word. 可能是词典的原因,也可能是程序的原因,这我无法确定。作者有空看下。

补充: 新牛津英汉双解大词典.zip

比如单词 be 《新牛津英汉双解大词典里》be/Be/BE 都是有的。但 be 查不到。 《欧路词典》则一次将三个都查了出来。

再补充一些不准确的单词:and、in、for、on、by、who、up

terasum commented 2 years ago

应该是 区分大小写的问题,这个问题会在后续的版本中新增参数解决,你可以试试查询一下精确匹配 Be/BE/be,如果都有的话就是大小写的问题了

tonyzhou1890 commented 2 years ago

应该是 区分大小写的问题,这个问题会在后续的版本中新增参数解决,你可以试试查询一下精确匹配 Be/BE/be,如果都有的话就是大小写的问题了

找到原因了。

  1. word 查询结果为 -word 这是因为《新牛津英汉双解大词典》的 stripKey 是 yes(词典不靠谱)。设置这个参数为 false 就可以查出来了。

    _stripKey() {
    // const stripKey =
    //   this.searchOptions.stripKey || common.isTrue(this.header.StripKey);
    const stripKey =
      this.searchOptions.stripKey ?? common.isTrue(this.header.StripKey);
    const regexp = common.REGEXP_STRIPKEY[this.ext];
    
    return stripKey
      ? function _s(key) {
          return key.replace(regexp, "$1");
        }
      : function _s(key) {
          return key;
        };
    }
  2. 关于 be/Be/BE 查询的问题。 这个也是词典的问题。
    { recordStartOffset: 5524403, keyText: 'be' },
    { recordStartOffset: 5539187, keyText: 'BE' },
    { recordStartOffset: 5539727, keyText: 'be-' },
    { recordStartOffset: 5542341, keyText: 'Be' },
    { recordStartOffset: 5542625, keyText: 'beach' },
    { recordStartOffset: 5545063, keyText: 'beach ball' },
    { recordStartOffset: 5545396, keyText: 'beach buggy' },
    { recordStartOffset: 5545727, keyText: 'beach bum' },
    { recordStartOffset: 5546068, keyText: 'beachcomber' },

    这个词典排序与你的预期不同,这导致按照字典序二分查找无法定位到要查的词。


《欧路词典》好像没有区分大小写,全部 stripKey 处理小写匹配。这就导致了查询一次返回多个相关单词。(不过欧路没返回 be-,可能我猜错了)

terasum commented 2 years ago

@tonyzhou1890 目前我正在处理各种词典排序不一致的问题,这个问题比较棘手

tonyzhou1890 commented 2 years ago

@tonyzhou1890 目前我正在处理各种词典排序不一致的问题,这个问题比较棘手

如果不在意启动时间的话,可以一次性解析所有的 key(这个函数你不建议使用),处理后存到一个新的 TypedArray 里面,为了降低下次启动时间,可以缓存 TypedArray 到文件。缓存到文件后,之后的处理就可以和现在的逻辑一样了,分块读取,二分查找。

对于 mdx 文件,我是将所有 key 存到了 uint8array 里,再用一个对象记录处理后(stripkey, lowercase)的 key 在 uint8array 的位置。(也试过 trie,但 trie 太占内存。js 的 Map 结构查找是 O(n) 复杂度,也不适用)(另外,缓存文件我没做)

这种方法只对 lookup 启用,因为我对这个函数有性能要求,反而启动时间我可以忍受(所以,缓存文件功能我没做)。返回结果的时候也是返回匹配单词的数组,而不是完全匹配的那一个。

目前,115 万词条的简明词典启动需要十几秒,内存占用一百多。查询性能提升 2 倍多。

另外,node11 已经提供了 TextEncoder 和 TextDecoder,建议就不要用第三方的库了。系统自带的性能好很多——内存更低,速度更快。

我想尽快结束手上的词典网站(本来是为了学英语,现在时间都花在写工具上了,本末倒置了。学完英语再好好捯饬工具吧),所以就修改后重新发了一个包(mdict-js)。

因为改动有点多,理念上也可能存在冲突,(以及,你们注释都用英文写的,我用的中文)就不提 pr 了。

改动后的代码我附件添加一下,希望可以帮到你。

js-mdict.zip

terasum commented 2 years ago

@tonyzhou1890 非常感谢你的反馈,最近这些问题也在困扰我,缓存的建议可以帮助我解决一些手头的问题非常感谢!

terasum commented 1 year ago

您好,我近期根据您的建议,重构了一些代码,整体与您的思路一致,近期我会针对您提供的问题和词典进行一段时间的测试,谢谢您的支持。