我在这里有一个字符串列表,
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。但是,我试图寻找类似的问题,但是找不到适合我的答案。
答案 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"