R语言 如何执行多个字符串模式替换而不重复先前的替换?

yyhrrdl8  于 2023-10-13  发布在  其他
关注(0)|答案(3)|浏览(91)

我想采取代数国际象棋符号和转换文件的字母(a,b,c,d,e,f,g,h)到北约音标(阿尔法,布拉沃,查理,回声,狐步舞,高尔夫,酒店),没有重复以前的替代品。我在R工作。
notation <- "1.d4 Nf6 2.c4 e6 3.g3 d5 4.Bg2 Be7 5.Nf3 0-0 6.0-0 dxc4 7.Qc2 a6 8.Qxc4 b5 9.Qc2 Bb7 10.Bd2 Ra7 "
预期结果:"1.delta 4 Nfoxtrot 6 2.charlie 4 echo 6 3.golf 3 delta 5"等等。我现在不在乎间隔。
如果我使用一个简单的字符串替换方法,替换将相互冲突。
使用gsub:

notation <- gsub("a", "alpha", notation)
notation <- gsub("b", "bravo", notation)
notation <- gsub("c", "charlie", notation)
notation <- gsub("d", "delta", notation)
notation <- gsub("e", "echo", notation)
notation <- gsub("f", "foxtrot", notation)
notation <- gsub("g", "golf", notation)
notation <- gsub("h", "hotel", notation)

产量"1.dechotelolta4 Nfoxtrot6 2.chotelarliechotelo4 echotelo6 3.golf3 dechotelolta5 4.Bgolf2 Bechotelo7 5.Nfoxtrot3 0-0 6.0-0 dechoteloltaxchotelarliechotelo4 7.Qchotelarliechotelo2 alphotela6 8.Qxchotelarliechotelo4 bravo5 9.Qchotelarliechotelo2 Bbravo7 10.Bdechotelolta2 Ralphotela7 "
“d”转换为“delta”,这很好。然而,“delta”包含字母“e”,因此变成了“decholta”。这里有一个“h”,所以结果变成了“dechotelolta”。
我还尝试了stringi库中的一个函数,但它也返回了类似的不希望的东西。

stri_replace_all_fixed(notation, 
                         c("a", "b", "c", "d", "e", "f", "g", "h"), 
                         c("alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel"), 
                         vectorise_all = FALSE)

我查看了他们的文档和几个SO问题,但找不到我需要的东西。
这个python question很接近,但仅限于单个字符替换。
因此,我正在寻找一个函数/方法,将取代多个模式,但我不希望取代文本覆盖/改变对方。
我现在最好的猜测是通过每次阅读notation一个字符,并将单个字符的副本或a-h字母的替换附加到新字符串来构建一个新字符串。但那感觉很不像有没有人有任何建议或知道一个库函数与所需的结果?

x8diyxa7

x8diyxa71#

nato <- c("alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliett", "kilo", "lima", "mike", "november", "oscar", "papa", "quebec", "romeo", "sierra", "tango", "uniform", "victor", "whiskey", "x-ray", "yankee", "zulu")
tr <- setNames(nato, letters)

stringr::str_replace_all(notation, "[a-z]", ~ tr[.x])
# [1] "1.delta4 Nfoxtrot6 2.charlie4 echo6 3.golf3 delta5 4.Bgolf2 Becho7 5.Nfoxtrot3 0-0 6.0-0 deltax-raycharlie4 7.Qcharlie2 alpha6 8.Qx-raycharlie4 bravo5 9.Qcharlie2 Bbravo7 10.Bdelta2 Ralpha7"

[a-z]将只匹配小写字母。str_replace_all的第三个参数是模式匹配的替换值。不经常使用的是你可以提供一个函数(从?str_replace_all):
或者,提供一个函数,该函数将为每个匹配(从右到左)调用一次,其返回值将用于替换匹配。

y3bcpkx1

y3bcpkx12#

基本R使用gregexprregmatches

phonetic <- c(a="alpha", b="bravo", c="charlie", d="delta", e="echo", f="foxtrot", g="golf", h="hotel")
gre <- gregexpr(paste0("[", paste(names(phonetic), collapse=""), "]"), notation)
regmatches(notation, gre)[[1]] <- phonetic[ regmatches(notation, gre)[[1]] ]
notation
# [1] "1.delta4 Nfoxtrot6 2.charlie4 echo6 3.golf3 delta5 4.Bgolf2 Becho7 5.Nfoxtrot3 0-0 6.0-0 deltaxcharlie4 7.Qcharlie2 alpha6 8.Qxcharlie4 bravo5 9.Qcharlie2 Bbravo7 10.Bdelta2 Ralpha7 "

我使用了看起来更复杂的paste(names(phonetic),collapse=""),因为您的示例包含了语音字母表的一个子集。如果您使用的是完整(a-z)版本,则不需要:

gre <- gregexpr("[a-z]", notation)
# ...
vwhgwdsa

vwhgwdsa3#

这个答案使用dplyrstringr通过将你的国际象棋符号转换成一个棋盘格来进行替换。这种方法的好处是让你更好地控制被替换的文本,因为你是一步一步地做的,而不是像其他答案那样只对一个函数做。
首先,我们将字符串分割成一个向量:

library(dplyr)
library(stringr)

notation <- "1.d4 Nf6 2.c4 e6 3.g3 d5 4.Bg2 Be7 5.Nf3 0-0 6.0-0 dxc4 7.Qc2 a6 8.Qxc4 b5 9.Qc2 Bb7 10.Bd2 Ra7 "

notation_split <- notation |> str_split(pattern = " ") |> unlist()

然后,我们用语音词典创建一个框架:

phonetic_dictionary <- tribble(~letter, ~word,
                               "a", "alpha",
                               "b", "bravo",
                               "c", "charlie",
                               "d", "delta",
                               "e", "echo",
                               "f", "foxtrot",
                               "g", "golf",
                               "h", "hotel")

我们将移动向量转换为一个字符串,然后提取我们想要替换的字母到语音单词中,然后使用left_join附加相应的语音单词,最后,我们将字母替换为单词:

replacement_table <- tibble(moves = notation_split) |> 
    mutate(letter = str_extract(moves, "a|b|c|d|e|f|g|h")) |> 
    left_join(phonetic_dictionary, join_by(letter)) |> 
    mutate(moves_phonetic = str_replace(moves, letter, paste0(" ", word, " "))) |> 
    mutate(moves_phonetic = ifelse(is.na(moves_phonetic), moves, moves_phonetic)) |> 
    print(n=Inf)

最后,我们提取结果列以给予您期望的结果:

replacement_table |> pull(moves_phonetic) |> paste(collapse = " ")
# [1] "1. delta 4 N foxtrot 6 2. charlie 4  echo 6 3. golf 3  delta 5 4.B golf 2 B echo 7 5.N foxtrot 3 0-0 6.0-0  delta xc4 7.Q charlie 2  alpha 6 8.Qx charlie 4  bravo 5 9.Q charlie 2 B bravo 7 10.B delta 2 R alpha 7 "

相关问题