根据某些条件更改字符串列表

时间:2020-02-21 17:19:50

标签: r string

我在这里有一个字符串列表,

List <- c('C8 H12 O1 Na1', 'C15 H20 O7 Na1', 'C18 H24 O6', 'C24 H32 O9 Na1', 'C26 H38 O5 Na1')

我想将其更改为

Listnew <- c('C8 H12 O1', 'C15 H20 O7', 'C18 H23 O6', 'C24 H32 O9', 'C26 H38 O5')

其中包含Na的任何字符串都已删除,而没有Na的任何字符串中的字符串中的H减少了1。 },List更改为'C18 H24 O6'。该列表包含在矩阵中。我知道如何根据一种条件更改字符串

我认为我需要先创建一个True / False列,以确定Na是否存在于该列的字符串中,然后使用该列从H字符串中减去“ 1”或删除Na。但是,我试图寻找类似的问题,但是找不到适合我的答案。

4 个答案:

答案 0 :(得分:2)

使用sub,我们可以最后删除Na\\d+,而用gsubfn减去1。

library(gsubfn)
new <- sub("\\sNa\\d+$", "", List)
i1 <- grep("\\bNa\\d+$", List, invert = TRUE)
new[i1] <- gsubfn("H\\d+", ~ paste0(substring(x,  1, 1),
    as.numeric(substring(x, 2))-1), new[i1])
new
#[1] "C8 H12 O1"  "C15 H20 O7" "C18 H23 O6" "C24 H32 O9" "C26 H38 O5"

或@G。格洛腾迪克评论了

new[i1] <- gsubfn("(H)(\\d+)", ~ paste0(x, as.numeric(y)-1), new[i1])     

答案 1 :(得分:1)

另一种方式可能是:

nums <- as.numeric(stringr::str_extract(List, '(?<=H)(\\d+)' ))-1
## subtracting every integer attached with H by 1
no_na <- grep('\\bNa\\d+\\b',List, invert = TRUE)
## picking the spot where Na is missing
replacement = unlist(lapply(no_na,function(x)gsub('(H)(\\d+)',paste0('\\1',nums[x]), List[x], perl = TRUE)))   
## replacing only that subtracted value which has no Na
List[no_na] <- replacement
## finally replacing using gsub Na followed by digit by ''
fout <- trimws(gsub('\\bNa\\d+\\b', '', List))

输出:

> fout
[1] "C8 H12 O1"  "C15 H20 O7" "C18 H23 O6" "C24 H32 O9"
[5] "C26 H38 O5"

答案 2 :(得分:1)

使用某些stringr函数,测试"\\bNa\\d+"的存在,提取H之后的数字,并将其减少。

library(stringr)

List %>%
  ifelse(str_detect(., "\\bNa\\d+"), 
         .,
         str_replace(., "(?<=\\bH)\\d+", as.character(as.integer(str_extract(., "(?<=\\bH)(\\d+)")) - 1L))) %>%
  str_remove_all("\\bNa\\d+") %>%
  trimws()
#> [1] "C8 H12 O1"  "C15 H20 O7" "C18 H23 O6" "C24 H32 O9" "C26 H38 O5"

为便于阅读,请将嵌套的东西拉出到函数中。

decrease_h <- function(x) {
  if (!str_detect(x, "\\bNa\\d+")) {
    n <- as.integer(str_extract(x, "(?<=\\bH)(\\d+)")) - 1L
    str_replace(x, "(?<=\\bH)\\d+", as.character(n))
  } else {
    x
  }
}

List %>%
  purrr::map_chr(decrease_h) %>% # or use sapply
  str_remove_all("\\bNa\\d+") %>%
  trimws()

答案 3 :(得分:0)

这是我在评论中建议的想法的实现-我们分解字符串,然后删除Na1或将H减1。然后我们paste全部返回并返回向量。

sapply(strsplit(List," "), function(x) {if (any(grepl("Na",x))) {x[grepl("Na",x)]<-""} else 
                                {x[grepl("H",x)]<-paste0("H",readr::parse_number(x[grepl("H",x)])-1)}
                             return(trimws(paste(x,collapse=" ")))
                            })

[1] "C8 H12 O1"  "C15 H20 O7" "C18 H23 O6" "C24 H32 O9" "C26 H38 O5"