str_replace_all 不是一次全部迭代地替换命名的向量元素
str_replace_all replacing named vector elements iteratively not all at once
假设我有一个长字符串: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" 和 "new") 或命名向量作为输入。
reprex 已编辑以便于人类阅读
函数的作用可能是有顺序的,所以在用s替换所有c之后,你用c替换所有s,只剩下c..
试试这个:
long_string %>% str_replace_all(c(c ="X", s = "U")) %>% str_replace_all(c(X ="s", U = "c"))
我的解决方法是利用 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)
当然,如果你需要放大,我建议使用更复杂的功能。
迭代行为是有意的。也就是说,我们可以使用自己的解决方法。我将使用 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"
所以在这里,在 rules
向量中查找 "a"
得到我们 "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"
我正在开发一个包来处理这类问题。这比 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"
假设我有一个长字符串: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" 和 "new") 或命名向量作为输入。
reprex 已编辑以便于人类阅读
函数的作用可能是有顺序的,所以在用s替换所有c之后,你用c替换所有s,只剩下c.. 试试这个:
long_string %>% str_replace_all(c(c ="X", s = "U")) %>% str_replace_all(c(X ="s", U = "c"))
我的解决方法是利用 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)
当然,如果你需要放大,我建议使用更复杂的功能。
迭代行为是有意的。也就是说,我们可以使用自己的解决方法。我将使用 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"
所以在这里,在 rules
向量中查找 "a"
得到我们 "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"
我正在开发一个包来处理这类问题。这比 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"