根据从头到尾的字符数在字符串中插入字符
Insert character in string conditional on number of characters from beginning and end
我有一个字符串列表,例如
myvar
[1] "VT" "AK" "AL2" "CA24" "NY12"
[6] "AZ6" "WY4"
我想在所有有3个字符的字符串的第二个字符后插入字符“0”,在所有有两个字符的字符串的末尾插入“01”,以获得输出
myvar
[1] "VT01" "AK01" "AL02" "CA24" "NY12"
[6] "AZ06" "WY04"
我以为我可以使用正则表达式前瞻和后视在一行中完成此操作,但我无法做更多的事情:
sub('(?<=.{2})(?=.{1})', '0', myvar, perl=T)
myvar
[1] "VT" "AK" "AL002" "CA024" "NY012"
[6] "AZ06" "WY04"
如有任何帮助,我们将不胜感激,
西蒙
我们可以使用 sub
提取数字部分,将字符串转换为 numeric
class,将 NA 值(从强制转换)更改为 1,然后使用 sprintf
粘贴非数字 (sub('\d+', ...)
) 和格式化数字部分。
v1 <- as.numeric(sub('\D+', '', myvar))
v1[is.na(v1)] <- 1
sprintf('%s%02d', sub('\d+', '', myvar),v1)
#[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
或使用gsubfn
。我们为那些没有任何数字元素的元素创建一个ifelse
条件并粘贴1。我们匹配gsubfn
(\d+
)中的数字部分,通过格式化替换它 sprintf
.
library(gsubfn)
gsubfn('\d+', ~sprintf('%02d', as.numeric(x)),
ifelse(!grepl('\d+', myvar), paste0(myvar, 1), myvar))
#[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
或者稍微更紧凑的版本是使用 sub
将 1 附加到那些没有数字部分的元素
gsubfn('\d+', ~sprintf('%02d', as.numeric(x)) ,sub('(?<=[A-Z])$', '1', myvar, perl=TRUE))
#[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
或者在没有环视的情况下使它更紧凑,
gsubfn('\d+', ~sprintf('%02d', as.numeric(x)), sub('(\D+)$', '\11', myvar))
#[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
关于静态剪切和粘贴的想法:
paste0(substr(myvar, 0, 2), sub("00", "01", gsub(" ", "0", sprintf("% 2s", substr(myvar, 3, 4)))))
# [1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
使用 substr 获取最后 2 个字符,将它们填充为 2 个字符,将空格替换为 0,然后将 00 替换为 01,粘贴前 2 个字符即可得到结果。
一个衬里(没有正则表达式,因为它们不是必需的,并且根本不能真正有用地确定替换尺寸,除非使用复杂的选择,然后用什么替换):
myvar[nchar(myvar)<4] <- paste0(myvar[nchar(myvar)<4],sprintf(paste0("%0",4-nchar(myvar[nchar(myvar)<4]),"i"),1))
目标是获得一个包含 4 个字符条目的向量,因此对于 4 个字符 (myvar[nchar(myvar)<4]
) 以下的所有条目,沿着长度为 4 减去实际条目长度的 0 左填充“1”打印它们。
with
可能有一种方法可以避免对 myvar[nchar(myvar)<4]
的冗余调用,但由于我不习惯,我实际上正在挖掘。
另一种选择(可以是单(长)衬里...):
mapply(function(x, dc_x){
if(nchar(x)<4) paste0(dc_x[1], "0", ifelse(length(dc_x)-1, dc_x[2], "1")) else x
},
x=myvar, dc_x=strsplit(myvar, "(?<=^.{2})", perl=T))
# VT AK AL2 CA24 NY12 AZ6 WY4
# "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
解释:
dc_x
是一个向量列表,myvar
的每个元素一个,第一项是 myvar
中对应项的第 2 个字符。因此,对于少于 4 个字符的元素,如果只有 2 个字符,则将前 2 个字符粘贴为“01”,如果超过 2 个字符,则粘贴“0”和字符串的其余部分。
您可以将 sub 或 gsub 命令的输出作为另一个 sub 或 gsub 命令的输入。
myvar <- c("VT", "AK", "AL2", "CA24", "NY12",
"AZ6", "WY4")
sub("^(.{2})$", "\101", sub("^(.{2})(.)$", "\10\2", myvar))
# [1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
我有一个字符串列表,例如
myvar
[1] "VT" "AK" "AL2" "CA24" "NY12"
[6] "AZ6" "WY4"
我想在所有有3个字符的字符串的第二个字符后插入字符“0”,在所有有两个字符的字符串的末尾插入“01”,以获得输出
myvar
[1] "VT01" "AK01" "AL02" "CA24" "NY12"
[6] "AZ06" "WY04"
我以为我可以使用正则表达式前瞻和后视在一行中完成此操作,但我无法做更多的事情:
sub('(?<=.{2})(?=.{1})', '0', myvar, perl=T)
myvar
[1] "VT" "AK" "AL002" "CA024" "NY012"
[6] "AZ06" "WY04"
如有任何帮助,我们将不胜感激,
西蒙
我们可以使用 sub
提取数字部分,将字符串转换为 numeric
class,将 NA 值(从强制转换)更改为 1,然后使用 sprintf
粘贴非数字 (sub('\d+', ...)
) 和格式化数字部分。
v1 <- as.numeric(sub('\D+', '', myvar))
v1[is.na(v1)] <- 1
sprintf('%s%02d', sub('\d+', '', myvar),v1)
#[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
或使用gsubfn
。我们为那些没有任何数字元素的元素创建一个ifelse
条件并粘贴1。我们匹配gsubfn
(\d+
)中的数字部分,通过格式化替换它 sprintf
.
library(gsubfn)
gsubfn('\d+', ~sprintf('%02d', as.numeric(x)),
ifelse(!grepl('\d+', myvar), paste0(myvar, 1), myvar))
#[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
或者稍微更紧凑的版本是使用 sub
将 1 附加到那些没有数字部分的元素
gsubfn('\d+', ~sprintf('%02d', as.numeric(x)) ,sub('(?<=[A-Z])$', '1', myvar, perl=TRUE))
#[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
或者在没有环视的情况下使它更紧凑,
gsubfn('\d+', ~sprintf('%02d', as.numeric(x)), sub('(\D+)$', '\11', myvar))
#[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
关于静态剪切和粘贴的想法:
paste0(substr(myvar, 0, 2), sub("00", "01", gsub(" ", "0", sprintf("% 2s", substr(myvar, 3, 4)))))
# [1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
使用 substr 获取最后 2 个字符,将它们填充为 2 个字符,将空格替换为 0,然后将 00 替换为 01,粘贴前 2 个字符即可得到结果。
一个衬里(没有正则表达式,因为它们不是必需的,并且根本不能真正有用地确定替换尺寸,除非使用复杂的选择,然后用什么替换):
myvar[nchar(myvar)<4] <- paste0(myvar[nchar(myvar)<4],sprintf(paste0("%0",4-nchar(myvar[nchar(myvar)<4]),"i"),1))
目标是获得一个包含 4 个字符条目的向量,因此对于 4 个字符 (myvar[nchar(myvar)<4]
) 以下的所有条目,沿着长度为 4 减去实际条目长度的 0 左填充“1”打印它们。
with
可能有一种方法可以避免对 myvar[nchar(myvar)<4]
的冗余调用,但由于我不习惯,我实际上正在挖掘。
另一种选择(可以是单(长)衬里...):
mapply(function(x, dc_x){
if(nchar(x)<4) paste0(dc_x[1], "0", ifelse(length(dc_x)-1, dc_x[2], "1")) else x
},
x=myvar, dc_x=strsplit(myvar, "(?<=^.{2})", perl=T))
# VT AK AL2 CA24 NY12 AZ6 WY4
# "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"
解释:
dc_x
是一个向量列表,myvar
的每个元素一个,第一项是 myvar
中对应项的第 2 个字符。因此,对于少于 4 个字符的元素,如果只有 2 个字符,则将前 2 个字符粘贴为“01”,如果超过 2 个字符,则粘贴“0”和字符串的其余部分。
您可以将 sub 或 gsub 命令的输出作为另一个 sub 或 gsub 命令的输入。
myvar <- c("VT", "AK", "AL2", "CA24", "NY12",
"AZ6", "WY4")
sub("^(.{2})$", "\101", sub("^(.{2})(.)$", "\10\2", myvar))
# [1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"