首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用列表中的匹配字符串替换字符串?

如何用列表中的匹配字符串替换字符串?
EN

Stack Overflow用户
提问于 2018-12-12 17:01:04
回答 3查看 106关注 0票数 2

假设我有一个列df1$z,其中包含一些“脏”字符串。

代码语言:javascript
复制
> df1$z
 [1] alpha uybkh   kilo-mdjfyrs  lima qxaucnpe gamma-qpnej  
 [5] beta-okmwy    beta-uybkh    gamma mdjfyrs lima qxaucnpe
 [9] beta qpnej    kilo okmwy   
9 Levels: alpha uybkh beta-okmwy beta-uybkh ... lima qxaucnpe

一些字符串以另一个向量a中包含的模式开始。

代码语言:javascript
复制
> a
[1] "alpha" "beta"  "gamma"

我希望用向量a-matching的对应模式替换z中的z a字符串,以便得到以下结果:

代码语言:javascript
复制
# [1] "alpha"         "kilo-mdjfyrs"  "lima qxaucnpe" "gamma"        
# [5] "beta"          "beta"          "gamma"         "lima qxaucnpe"
# [9] "beta"          "kilo okmwy" 

我编写了一个函数,使我更加接近,但它不是一次就替换了字符串,而且我无法将所有的东西组合在一起:

代码语言:javascript
复制
> lapply(seq_along(a), function(x) {z[grep(paste0("^", a[x]), z)] <- a[x]; z})
[[1]]
 [1] "beta sfrmyijl" "lima-xudwfkm"  "lima-kirvpys"  "gamma wriygcb"
 [5] "alpha"         "alpha"         "kilo xudwfkm"  "alpha"        
 [9] "gamma wriygcb" "kilo-wvxgar"  

[[2]]
 [1] "beta"           "lima-xudwfkm"   "lima-kirvpys"   "gamma wriygcb" 
 [5] "alpha wvxgar"   "alpha-sfrmyijl" "kilo xudwfkm"   "alpha-kirvpys" 
 [9] "gamma wriygcb"  "kilo-wvxgar"   

[[3]]
 [1] "beta sfrmyijl"  "lima-xudwfkm"   "lima-kirvpys"   "gamma"         
 [5] "alpha wvxgar"   "alpha-sfrmyijl" "kilo xudwfkm"   "alpha-kirvpys" 
 [9] "gamma"          "kilo-wvxgar"   

我在一些mapply()方法上也失败了,我认为这些方法在这里可能会有所帮助,我还研究了一些现有的答案,比如this one,虽然我无法适应具体的问题。

那么,我如何以一个有效的基数R的方式来完成这个任务呢?请注意,替换应该返回到数据帧df1中,而不会干扰行的顺序。

数据

代码语言:javascript
复制
a <- c("alpha", "beta", "gamma")
set.seed(105056)
z <- paste0(sample(c(a, "kilo", "lima"), 10, replace=TRUE), 
            sample(c("-", " "), 10, replace=TRUE), 
            replicate(5, paste0(sample(letters, sample(5:9)), collapse="")))
df1 <- data.frame(z, x=rnorm(10))
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-12-12 17:31:19

您可以使用以下sub解决方案:

代码语言:javascript
复制
> sub(paste0(".*\\b(",paste(a, collapse="|"),")\\b.*"), "\\1", df1$z)
 [1] "alpha"         "kilo-mdjfyrs"  "lima qxaucnpe" "gamma"         "beta"         
 [6] "beta"          "gamma"         "lima qxaucnpe" "beta"          "kilo okmwy"

该模式将匹配a向量中关键字之前和之后的任何字符,并将关键字捕获到Group 1中,而\1替换模式只保留查找的关键字,并在该关键字之前和之后丢弃所有文本。如果没有匹配,就不会有任何变化。

regex demo

票数 1
EN

Stack Overflow用户

发布于 2018-12-12 17:30:57

我们可以用sub。在从'a‘中创建一个字符串之后,用paste创建一个模式,然后使用它来捕获替换中带有反向引用(\\1)的模式

代码语言:javascript
复制
sub(paste0(".*\\b(", paste(a, collapse="|"), ")\\b.*"), "\\1", df1$z)
#[1] "alpha"         "kilo-mdjfyrs"  "lima qxaucnpe" "gamma"         "beta"          "beta"          "gamma"        
#[8] "lima qxaucnpe" "beta"          "kilo okmwy"   

注意:sub解决方案是在这里首先发布的

或者使用来自stringrstringr

代码语言:javascript
复制
library(tidyverse)
df1 %>% 
  mutate(z = str_replace(z, 
      paste0(".*\\b(", paste(a, collapse="|"), ")\\b.*"), "\\1"))
#           z           x
#1          alpha -0.18973111
#2   kilo-mdjfyrs -0.88150363
#3  lima qxaucnpe  0.01665189
#4          gamma  0.62647841
#5           beta -0.29526632
#6           beta  0.42480082
#7          gamma  1.03653486
#8  lima qxaucnpe -1.51910745
#9           beta  1.21504343
#10    kilo okmwy  1.25321421
票数 0
EN

Stack Overflow用户

发布于 2018-12-12 20:21:12

下面是一个更长但不那么不透明的解决方案,使用ifelsegrepl

代码语言:javascript
复制
df1$z <- ifelse(grepl("alpha.*", df1$z), a[1],
            ifelse(grepl("beta.*", df1$z), a[2],
                   ifelse(grepl("gamma.*", df1$z), a[3], as.character(df1$z))))
df1
               z           x
1          alpha -0.18973111
2   kilo-mdjfyrs -0.88150363
3  lima qxaucnpe  0.01665189
4          gamma  0.62647841
5           beta -0.29526632
6           beta  0.42480082
7          gamma  1.03653486
8  lima qxaucnpe -1.51910745
9           beta  1.21504343
10    kilo okmwy  1.25321421
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53747918

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档