我们如何 return R中两个字符串中的公共字符数?
How can we return the number of common characters in two strings in R?
我要搜索两个字符串和return常见字符的个数。所以,如果我们有
s1 = "aabcc"
s2 = "adcaa"
输出应该是 solution(s1, s2) = 3
。 (s1 和 s2 有 3 个共同字符 - 2 个“a”和 1 个“c”。)
我的想法是使用粘贴连接两个字符串,然后检查新字符串中每个不同字符的计数。如果计数是偶数,我会将该计数的一半加到计数变量中(因此,如果我们有四个 a,那么我们就有两对),如果某个字符的计数是奇数,那么我们减去一个并添加该数字的一半到我们的计数(有效地忽略了无法配对的字符的额外出现。
我想也许我可以通过将我们的字符放入一个 data.frame 中来做到这一点,它记录了每个字母的计数,但是这样做的代码变得非常长:
df <- as.data.frame(paste(s1,s2,sep="") %>%
## keep first column only and name it 'characters':
select('characters' = 1) %>%
## multiple cell values (as separated by a blank)
## into separate rows:
separate_rows(characters, sep = " ") %>%
group_by(characters) %>%
summarise(count = n()) %>%
arrange(desc(count))
所以我现在认为我把这整件事复杂化了。谁能指出我正确的方向?我最初的想法是明智的还是离谱的?
澄清:字符串的长度不一定相同,但它们的长度始终在 1 到 14 个字符之间。
澄清 2:理想的解决方案将在基础 R 中(无包),因为这是我首先想要胜任的,但仍然欢迎所有其他解决方案
inner_join(as.data.frame(table(strsplit(s1, "") )),
as.data.frame(table(strsplit(s2, "") )),
by = "Var1") %>%
mutate(Freq.diff = pmin(Freq.x, Freq.y)) %>%
pull(Freq.diff) %>%
sum()
或仅使用基数 R:
df <- merge(as.data.frame(table(strsplit(s1, ""))),
as.data.frame(table(strsplit(s2, ""))),
by = 1)
sum(pmin(df$Freq.x, df$Freq.y))
这里的做法是先strsplit()
字符串,然后vecsets::vintersect()
输出相交字符(重复字符也会显示)。然后输出相交字符的length
。
这应该适用于具有不同长度的字符串。
library(vecsets)
length(vintersect(strsplit(s1, "")[[1]], strsplit(s2, "")[[1]]))
[1] 3
另一个可能的解决方案:
library(tidyverse)
s1 = "aabcc"
s2 = "adcaa"
data.frame(x = table(str_split(s1,"", simplify = T)[1,])) %>%
inner_join(data.frame(x = table(str_split(s2,"", simplify = T)[1,])), by="x.Var1") %>%
apply(1, min) %>% as.numeric %>% sum
#> [1] 3
我要搜索两个字符串和return常见字符的个数。所以,如果我们有
s1 = "aabcc"
s2 = "adcaa"
输出应该是 solution(s1, s2) = 3
。 (s1 和 s2 有 3 个共同字符 - 2 个“a”和 1 个“c”。)
我的想法是使用粘贴连接两个字符串,然后检查新字符串中每个不同字符的计数。如果计数是偶数,我会将该计数的一半加到计数变量中(因此,如果我们有四个 a,那么我们就有两对),如果某个字符的计数是奇数,那么我们减去一个并添加该数字的一半到我们的计数(有效地忽略了无法配对的字符的额外出现。
我想也许我可以通过将我们的字符放入一个 data.frame 中来做到这一点,它记录了每个字母的计数,但是这样做的代码变得非常长:
df <- as.data.frame(paste(s1,s2,sep="") %>%
## keep first column only and name it 'characters':
select('characters' = 1) %>%
## multiple cell values (as separated by a blank)
## into separate rows:
separate_rows(characters, sep = " ") %>%
group_by(characters) %>%
summarise(count = n()) %>%
arrange(desc(count))
所以我现在认为我把这整件事复杂化了。谁能指出我正确的方向?我最初的想法是明智的还是离谱的?
澄清:字符串的长度不一定相同,但它们的长度始终在 1 到 14 个字符之间。
澄清 2:理想的解决方案将在基础 R 中(无包),因为这是我首先想要胜任的,但仍然欢迎所有其他解决方案
inner_join(as.data.frame(table(strsplit(s1, "") )),
as.data.frame(table(strsplit(s2, "") )),
by = "Var1") %>%
mutate(Freq.diff = pmin(Freq.x, Freq.y)) %>%
pull(Freq.diff) %>%
sum()
或仅使用基数 R:
df <- merge(as.data.frame(table(strsplit(s1, ""))),
as.data.frame(table(strsplit(s2, ""))),
by = 1)
sum(pmin(df$Freq.x, df$Freq.y))
这里的做法是先strsplit()
字符串,然后vecsets::vintersect()
输出相交字符(重复字符也会显示)。然后输出相交字符的length
。
这应该适用于具有不同长度的字符串。
library(vecsets)
length(vintersect(strsplit(s1, "")[[1]], strsplit(s2, "")[[1]]))
[1] 3
另一个可能的解决方案:
library(tidyverse)
s1 = "aabcc"
s2 = "adcaa"
data.frame(x = table(str_split(s1,"", simplify = T)[1,])) %>%
inner_join(data.frame(x = table(str_split(s2,"", simplify = T)[1,])), by="x.Var1") %>%
apply(1, min) %>% as.numeric %>% sum
#> [1] 3