我们说我有一个很长的字符串:pneumonoultramicroscopicsilicovolcanoconiosis。我想使用stringr::str_replace_all
替换某些字母。根据文档,str_replace_all
可以使用命名向量并用值替换名称。这适用于1次替换,但对于多次,它似乎迭代地进行,因此结果是替换prelast迭代。我不确定这是预期的行为。
library(tidyverse)
text_string = "developer"
text_string %>%
str_replace_all(c(e ="X")) #this works fine
[1] "dXvXlopXr"
text_string %>%
str_replace_all(c(e ="p", p = "e")) #not intended behaviour
[1] "develoeer"
期望的结果:
[1] "dpvploepr"
我通过介绍一个新角色来获得:
text_string %>%
str_replace_all(c(e ="X", p = "e", X = "p"))
这是一种可行的解决方法,但几乎不可能。这是一个错误还是我的期望错了?
我也希望能够同时用 n 其他字母替换 n 字母,最好使用两个向量(例如" old&# 34;和" new")或命名向量作为输入。
编辑reprex以便于人类阅读
答案 0 :(得分:2)
我正在开发一个处理问题类型的软件包。这比qdap::mgsub
函数更安全,因为它不依赖于占位符。它完全支持正则表达式作为匹配和替换。您提供了一个命名列表,其中名称是要匹配的字符串,它们的值是替换值。
devtools::install_github("bmewing/mgsub")
library(mgsub)
mgsub("developer",list("e" ="p", "p" = "e"))
#> [1] "dpvploepr"
qdap::mgsub(c("e","p"),c("p","e"),"developer")
#> [1] "dpvploppr"
答案 1 :(得分:1)
我的解决方法是利用str_replace_all可以将函数作为替换的输入这一事实。
library(stringr)
text_string = "developer"
pattern <- "p|e"
fun <- function(query) {
if(query == "e") y <- "p"
if(query == "p") y <- "e"
return(y)
}
str_replace_all(text_string, pattern, fun)
当然,如果你需要扩大规模,我建议使用更复杂的功能。
答案 2 :(得分:0)
函数可能有一个命令,所以在用s替换所有c后,用c替换所有s,只剩下c ... 试试这个:
long_string %>% str_replace_all(c(c ="X", s = "U")) %>% str_replace_all(c(X ="s", U = "c"))
答案 3 :(得分:0)
意图是迭代行为。也就是说,我们可以使用自己的解决方法。我将使用character subsetting进行替换。
在命名向量中,我们可以按名称查找事物并获取每个名称的替换值。这就像同时进行所有替换一样。
rules <- c(a = "X", b = "Y", X = "a")
chars <- c("a", "a", "b", "X", "X")
rules[chars]
#> a a b X X
#> "X" "X" "Y" "a" "a"
所以在这里,在"a"
向量中查找rules
会让我们"X"
,有效地将"a"
替换为"X"
。其他角色也一样。
一个问题是没有匹配的名称会产生NA
。
rules <- c(a = "X", b = "Y", X = "a")
chars <- c("a", "Y", "Z")
rules[chars]
#> a <NA> <NA>
#> "X" NA NA
为了防止NA出现,我们可以扩展规则以包含任何新字符,以便字符被其自身替换。
rules <- c(a = "X", b = "Y", X = "a")
chars <- c("a", "Y", "Z")
no_rule <- chars[! chars %in% names(rules)]
rules2 <- c(rules, setNames(no_rule, no_rule))
rules2[chars]
#> a Y Z
#> "X" "Y" "Z"
这就是以下功能背后的逻辑。
library(stringr)
str_replace_chars <- function(string, rules) {
# Expand rules to replace characters with themselves
# if those characters do not have a replacement rule
chars <- unique(unlist(strsplit(string, "")))
complete_rules <- setNames(chars, chars)
complete_rules[names(rules)] <- rules
# Split each string into characters, replace and unsplit
for (string_i in seq_along(string)) {
chars_i <- unlist(strsplit(string[string_i], ""))
string[string_i] <- paste0(complete_rules[chars_i], collapse = "")
}
string
}
rules <- c(a = "X", p = "e", e = "p")
string <- c("application", "developer")
str_replace_chars(string, rules)
#> [1] "XeelicXtion" "dpvploepr"