用异常替换重复的字母
Replace duplicate letters with exception
我正在尝试用一个字母替换任何重复的字母。
我在这里使用 gsub
并且它正在工作:
text <- c("This tree is veeeeery tall")
gsub("([a-zA-Z])\1+", "\1", text)
##[1] "This tre is very tal"
但是 我需要为某些单词例外:
"This tree is very tall"
我尝试了这个问题的解决方案,但它不起作用。
text <- c("This tree is veeeeery tall")
words2keep <- c("tree", "tall")
gsub(perl=T,paste0('(?!\b',paste(collapse='\b|\b',words2keep),'\b)\b([a-zA-Z])\1+\b'),'\1',text)
##[1] "This tree is veeeeery tall"
那么,有什么办法吗?
这是 stringr
中 str_replace_all
的解决方案:
text1 <- c("This tree is veeeeery tall")
text2 <- c("This tree is vaeeeeery tall")
text3 <- c("This tree is eeeeery tall")
words2keep <- c("tree", "tall")
library(stringr)
replace_func = function(string){
str_replace_all(string, "(\w)\1+", "\1")
}
names(words2keep) = replace_func(words2keep)
text_clean1 = replace_func(text1)
str_replace_all(text_clean1, words2keep)
# [1] "This tree is very tall"
text_clean2 = replace_func(text2)
str_replace_all(text_clean2, words2keep)
# [1] "This tree is vaery tall"
text_clean3 = replace_func(text3)
str_replace_all(text_clean3, words2keep)
# [1] "This tree is ery tall"
此解决方案首先通过 text
将要通过的相同 str_replace_all
运行 words2keep
,并使结果成为 words2keep
的名称:
> words2keep
tre tal
"tree" "tall"
然后将相同的 str_replace_all
应用于 text
以删除所有重复的单词字符:
> replace_func(text1)
[1] "This tre is very tal"
最后,技巧是使用第三个 str_replace_all
通过提供 named words2keep
向量将错误修改的词替换为原始词。
使用 PCRE perl=TRUE
选项,很容易向正则表达式引入异常。您所需要的只是一个交替运算符,它将分隔两个主要部分:第一个,左边的部分是我们匹配和跳过的部分,第二个是我们要实际处理的部分。
\b(?:tree|tall)\b(*SKIP)(*F)|([a-zA-Z])+
详情
\b(?:tree|tall)\b(*SKIP)(*F)
- 前导单词边界、整个单词 tree
或 tall
、尾随单词边界以及 2 个 PCRE 动词的组合 (*SKIP)(*F)
让正则表达式引擎跳过匹配并从当前位置继续寻找下一个(跳过的匹配结束)
|
- 或
([a-zA-Z])+
- 捕获到第 1 组的任何 ASCII 字母,然后同一字母的一个或多个重复(请注意 \p{L}
和 (*UCP)
动词使模式完全支持 Unicode )
要在 R 中动态构建正则表达式,您需要 paste
将异常词向量放入正则表达式的左侧:
text <- c("This tree is veeeeery tall")
words2keep <- c("tree", "tall")
p <- paste0('\b(?:',paste(collapse='|',words2keep),')\b(*SKIP)(*F)|([A-Za-z])\1+')
## OR: p <- paste0('(*UCP)\b(?:',paste(collapse='|',words2keep),')\b(*SKIP)(*F)|(\p{L})\1+')
p
## => [1] "\b(?:tree|tall)\b(*SKIP)(*F)|([A-Za-z])\1+"
gsub(p, '\1',text, perl=TRUE)
## => [1] "This tree is very tall"
我正在尝试用一个字母替换任何重复的字母。
我在这里使用 gsub
并且它正在工作:
text <- c("This tree is veeeeery tall")
gsub("([a-zA-Z])\1+", "\1", text)
##[1] "This tre is very tal"
但是 我需要为某些单词例外:
"This tree is very tall"
我尝试了这个问题的解决方案
text <- c("This tree is veeeeery tall")
words2keep <- c("tree", "tall")
gsub(perl=T,paste0('(?!\b',paste(collapse='\b|\b',words2keep),'\b)\b([a-zA-Z])\1+\b'),'\1',text)
##[1] "This tree is veeeeery tall"
那么,有什么办法吗?
这是 stringr
中 str_replace_all
的解决方案:
text1 <- c("This tree is veeeeery tall")
text2 <- c("This tree is vaeeeeery tall")
text3 <- c("This tree is eeeeery tall")
words2keep <- c("tree", "tall")
library(stringr)
replace_func = function(string){
str_replace_all(string, "(\w)\1+", "\1")
}
names(words2keep) = replace_func(words2keep)
text_clean1 = replace_func(text1)
str_replace_all(text_clean1, words2keep)
# [1] "This tree is very tall"
text_clean2 = replace_func(text2)
str_replace_all(text_clean2, words2keep)
# [1] "This tree is vaery tall"
text_clean3 = replace_func(text3)
str_replace_all(text_clean3, words2keep)
# [1] "This tree is ery tall"
此解决方案首先通过 text
将要通过的相同 str_replace_all
运行 words2keep
,并使结果成为 words2keep
的名称:
> words2keep
tre tal
"tree" "tall"
然后将相同的 str_replace_all
应用于 text
以删除所有重复的单词字符:
> replace_func(text1)
[1] "This tre is very tal"
最后,技巧是使用第三个 str_replace_all
通过提供 named words2keep
向量将错误修改的词替换为原始词。
使用 PCRE perl=TRUE
选项,很容易向正则表达式引入异常。您所需要的只是一个交替运算符,它将分隔两个主要部分:第一个,左边的部分是我们匹配和跳过的部分,第二个是我们要实际处理的部分。
\b(?:tree|tall)\b(*SKIP)(*F)|([a-zA-Z])+
详情
\b(?:tree|tall)\b(*SKIP)(*F)
- 前导单词边界、整个单词tree
或tall
、尾随单词边界以及 2 个 PCRE 动词的组合(*SKIP)(*F)
让正则表达式引擎跳过匹配并从当前位置继续寻找下一个(跳过的匹配结束)|
- 或([a-zA-Z])+
- 捕获到第 1 组的任何 ASCII 字母,然后同一字母的一个或多个重复(请注意\p{L}
和(*UCP)
动词使模式完全支持 Unicode )
要在 R 中动态构建正则表达式,您需要 paste
将异常词向量放入正则表达式的左侧:
text <- c("This tree is veeeeery tall")
words2keep <- c("tree", "tall")
p <- paste0('\b(?:',paste(collapse='|',words2keep),')\b(*SKIP)(*F)|([A-Za-z])\1+')
## OR: p <- paste0('(*UCP)\b(?:',paste(collapse='|',words2keep),')\b(*SKIP)(*F)|(\p{L})\1+')
p
## => [1] "\b(?:tree|tall)\b(*SKIP)(*F)|([A-Za-z])\1+"
gsub(p, '\1',text, perl=TRUE)
## => [1] "This tree is very tall"