Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS 中文转换拼音的实现 #189

Open
toFrankie opened this issue Feb 26, 2023 · 0 comments
Open

JS 中文转换拼音的实现 #189

toFrankie opened this issue Feb 26, 2023 · 0 comments
Labels
2019 2019 年撰写 前端 与 JavaScript、ECMAScript、Web 前端相关的文章

Comments

@toFrankie
Copy link
Owner

toFrankie commented Feb 26, 2023

写在前面

或许你需要的是:

需求

此前项目中有一个中文转拼音的需求,于是整理了一下实现方法。

在转换过程中,这里我保留了数字和字母,其他特殊字符或者空格将会被去掉。如 测试 会被转换成 CeShi。(可自行修改 convert2Pinyin() 方法实现其他需求)

实现

话不多说(Github Demo

<!-- html -->
<input id="input" value="测试" />
<input id="output" disabled />
// js
window.onload = () => {
  const input = document.getElementById('input')
  const output = document.getElementById('output')

  // 失焦进行转换
  input.addEventListener('blur', () => {
    const val = input.value
    output.value = convertToPinyin(val)
  })

  /**
   * 转换成拼音(若有空格、特殊字符将被移除)
   *
   * @param {string} sourceStr 原始数据
   */
  const convertToPinyin = sourceStr => {
    // 目标数据
    let targetStr = ''
    // 匹配中文
    const cnReg = /[\u4e00-\u9fa5]/
    // 匹配数字和英文
    const enReg = /[a-zA-Z0-9]/
    // 保留英文和数字
    const keep = true

    // 遍历源数据
    for (let i = 0, len = sourceStr.length; i < len; i++) {
      const str = sourceStr.substr(i, 1)
      if (keep && enReg.test(str)) {
        targetStr += str
      } else if (cnReg.test(str)) {
        const searchResult = searchPinYin(str, PinYin)
        if (searchResult) {
          // targetStr += searchResult
          targetStr += capitalize(searchResult) // 首字母大写
        }
      }
    }

    return targetStr
  }

  /**
   * 检索拼音
   *
   * @param {string} str 源字符串
   * @param {object} data 收集的拼音 Unicode 编码集合
   */
  const searchPinYin = (str, data) => {
    for (const key in data) {
      if (data.hasOwnProperty(key) && data[key].indexOf(str) !== -1) {
        return key
      }
    }
    return ''
  }

  /**
   * 将拼音首字母转换为大写
   *
   * @param {string} str 源字符串
   */
  const capitalize = str => {
    if (str) {
      const [first] = str
      const other = str.replace(/^\S/, '')
      return `${first.toUpperCase()}${other}`
    }
    return str
  }

  /**
   * 目前这个 16 进制 Unicode 编码是网上收集的,可能不能覆盖所有的中文字符,可以自行补充;
   *
   * 例如:‘婋’(xiao)字:
   * 1、使用 '婋'.charCodeAt(0).toString(16) 得到 Unicode 编码:5a4b;
   * 2、将编码前面加上:\u => \u5a4b;
   * 3、然后放到对象 PinYin['xiao'] 里面。
   *
   * 现在只想到了这种笨方法一个一个往里补充,如果有更好的方法,欢迎指出!!!
   */
  const PinYin = {
    a: '\u554a\u963f\u9515'
    // ...
    // 由于这块代码太多,这里省略就不贴上来了,麻烦请看 GitHub Demo。
  }
}

难点

其实在中文转拼音的过程中,比较麻烦的在于 多音字生僻字 的实现,我想到的解决思路是:

  1. 生僻字:是由于 PinYin 里面列举的缺失一些中文字符,可通过 str.charCodeAt(0).toString(16) 的方式补充,具体方法不再赘述,上面有说明。

  2. 多音字:其实多音字一直是最麻烦的地方,因为每一个中文字符只有一个对应的 Unicode 编码,所以需要在对象的多个对应属性上添加编码。
    字,通过 '曾'.charCodeAt(0).toString(16) 获取到 66fe,然后前面拼接上 \u,得到 \u66fe

// 截取 PinYin 一小部分
const PinYin = {
  ceng: '\u66fe',
  zeng: '\u66fe'
}

然后修改上述 convert2Pinyin()searchPinYin() 方法,把符合规则的字符返回一个数组,然后用排列组合的方式列出所有可能。

GitHub

仓库除了拼音转中文之外,还有其他实用方法,麻烦移步查看。如有更好的实现方法,欢迎留言,谢谢!

@toFrankie toFrankie added the 前端 与 JavaScript、ECMAScript、Web 前端相关的文章 label Feb 26, 2023
@toFrankie toFrankie added the 2019 2019 年撰写 label Apr 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2019 2019 年撰写 前端 与 JavaScript、ECMAScript、Web 前端相关的文章
Projects
None yet
Development

No branches or pull requests

1 participant