uribo / zipangu

Japanese utility functions and data
https://uribo.github.io/zipangu
Other
56 stars 7 forks source link

文字列正規化関数を実装する #13

Closed teramonagi closed 2 years ago

teramonagi commented 4 years ago

RのUnicode正規化関数(パッケージ)を作ってみた これをモダナイズする

teramonagi commented 4 years ago

またはこれにならう https://github.com/ikegami-yukino/neologdn/blob/master/README.rst

yutannihilation commented 4 years ago

stringiの関数ではだめなんですか?

teramonagi commented 4 years ago

はええよw

teramonagi commented 4 years ago

理解した、これのR版を実装する https://github.com/neologd/mecab-ipadic-neologd/wiki/Regexp.ja#python-written-by-hideaki-t--overlast

yutannihilation commented 4 years ago

いや、stri_trans_nfkcとかの存在に気付いてないだけなのかなと思い...。知ってるなら大丈夫です!

uribo commented 4 years ago

stringiの関数をラップした str_conv_normalize() が用意されています。

library(zipangu)
x <- "\u2460"
print(x)
#> [1] "①"
str_conv_normalize(x, "nfkc")
#> [1] "1"
str_conv_normalize("㍿ホクソエム", to = "nfkc")
#> [1] "株式会社ホクソエム"

Created on 2020-03-17 by the reprex package (v0.3.0)

uribo commented 4 years ago

neologdのリンクのような冗長な文字列を削除するのは正規化とは少し違うような。関数としてあっても良いと思いますが、 str_conv_normalize() とは分けたいです。

paithiov909 commented 3 years ago

この話なんですが、これを移植してもらえませんか。こういう関数は個人的によくほしくなる場面があるのですが、自作パッケージに置いているとやや使い回ししづらいので、zipanguに似た関数があると便利に思います。

uribo commented 3 years ago

@paithiov909 ありがとうございます。neologdベースでの関数ですね。是非テストコード込みでプルリクエスト頂ければ幸いです。

一点、 解析対象テキストの先頭と末尾の半角スペースは削除 こちらが未実装なように思いますが、この機能を含める点についてはどうでしょうか。

paithiov909 commented 3 years ago

@uribo つぎ足しで書いていたため、私的にはそこまで忠実にneologdの処理に沿った実装は求めていませんでした。より忠実に同じような処理をするならだいたい次のような感じかと思うので、zipanguにはこちらを追加するつもりで作業しようと思います。

require(magrittr)
#>  要求されたパッケージ magrittr をロード中です
#> Warning: パッケージ 'magrittr' はバージョン 4.0.3 の R の下で造られました

normalize <- function(str) {
    res <- str %>%
        stringi::stri_trans_nfkc() %>%
        stringr::str_replace_all("\u2019", "\'") %>%
        stringr::str_replace_all("\u201d", "\"") %>%
        stringr::str_replace_all("[\\-\u02d7\u058a\u2010\u2011\u2012\u2013\u2043\u207b\u208b\u2212]+", "-") %>%
        stringr::str_replace_all("[\ufe63\uff0d\uff70\u2014\u2015\u2500\u2501\u30fc]+", enc2utf8("\u30fc")) %>%
        stringr::str_replace_all("([:blank:]){2,}", " ") %>%
        stringr::str_replace_all(
            paste0(
                "([\u0021-\u007e\uff10-\uff19\u3041-\u3093\u30a1-\u30f6\u30fc\u4e00-\u9fa0[:punct:]]*)",
                "[[:blank:]]*",
                "([\uff10-\uff19\u3041-\u3093\u30a1-\u30f6\u30fc\u4e00-\u9fa0[:punct:]]+)"
            ),
            "\\1\\2") %>%
        stringr::str_replace_all(
            paste0(
                "([\uff10-\uff19\u3041-\u3093\u30a1-\u30f6\u30fc\u4e00-\u9fa0[:punct:]]+)",
                "[[:blank:]]*",
                "([\u0021-\u007e[:punct:]]+)"
            ),
            "\\1\\2") %>%
        stringr::str_remove_all("[~\u223c\u223e\u301c\u3030\uff5e]+") %>%
        stringr::str_remove_all("^[:space:]|[:space:]$") %>%
        stringr::str_remove_all("[[:cntrl:]]+")
    return(res)
}

normalize("~~~スーパーーーーCoding the Matrix PRML 副 読 本 アルゴリズム C 検索 エンジン 自作 入門 を 買い ました!!!")
#> [1] "スーパーCoding the Matrix PRML副読本アルゴリズムC検索エンジン自作入門を買いました!!!"
normalize("   南アルプスの 天然水- Sparking Lemon レモン一絞り   ")
#> [1] "南アルプスの天然水-Sparking Lemonレモン一絞り"
normalize(" 南アルプスの 天然水- Sparking* Lemon+ レモン一絞り ")
#> [1] "南アルプスの天然水-Sparking* Lemon+レモン一絞り"

Created on 2021-02-20 by the reprex package (v1.0.0)

確認ですが、関数名はどうすればよいですか?

uribo commented 3 years ago

@paithiov909 関数名はお任せしますが、 str_jconv のドキュメントがあるので、それと分けつつ共通性を持たせて str_normalize() ではどうでしょうか。 (この関数があれば str_conv_normalize(to = "nfkc")は廃止しても良いかもしれませんね)

あと細かい好みの問題ですが、 stringr::str_replace_all() で置換する処理は str_replace_all(c("\u201d" = "\"", "\u2019" = "\'")) のようにc()でまとめてしまっても良い気がします。 さらに空白処置は stringr::str_squish() で代用するという手もあります。