我想创建一个带有两个参数的函数,它将显示给定单词中字符的频率:x< - word,y< - letter。所以,我创建了以下函数:
frequency <- function(x,y)
{
word <- strsplit(x,"")
counter <- 0
for (i in 1:length(word)){
if (word[i] == y) counter=counter+1
}
print(counter)
}
这个函数的基本思想是分割给定单词的字符,迭代它们并在满足条件时增加计数器的值。但是,此函数始终返回值0.这是什么原因?
答案 0 :(得分:3)
另一个版本是翻译你的单词&#39;进入raw()
向量并与&#39;字母进行比较&#39;作为raw()
向量。
frequency = function(word, letter)
sum(charToRaw(word) == charToRaw(letter))
以下是四种不同的解决方案
f0 <- function(word, letter)
sum(strsplit(word, "")[[1]] == letter)
f1 <- function(word, letter)
sum(charToRaw(word) == charToRaw(letter))
f2a <- function(word, letter)
length(unlist(gregexpr(letter, word)))
f2b <- function(word, letter)
length(unlist(gregexpr(letter, word, fixed=TRUE)))
有一些正确性和性能比较
> word <- "foo"
> letter <- "o"
> identical(f0(word, letter), f1(word, letter))
[1] TRUE
> identical(f0(word, letter), f2a(word, letter))
[1] TRUE
> identical(f0(word, letter), f2b(word, letter))
[1] TRUE
> letter <- "a"
> identical(f0(word, letter), f1(word, letter))
[1] TRUE
> identical(f0(word, letter), f2a(word, letter))
[1] FALSE
> identical(f0(word, letter), f2b(word, letter))
[1] FALSE
> word <- paste(sample(letters, 10000, TRUE), collapse="")
> letter <- "a"
> microbenchmark(
+ f0(word, letter), f1(word, letter),
+ f2a(word, letter), f2b(word, letter)
+ )
Unit: microseconds
expr min lq mean median uq max neval
f0(word, letter) 558.433 562.4755 579.03451 583.5590 584.8920 628.946 100
f1(word, letter) 71.482 78.7100 100.85787 80.0275 81.7035 2195.366 100
f2a(word, letter) 277.618 278.7280 280.94280 279.4870 280.4270 302.683 100
f2b(word, letter) 66.888 68.1800 69.07205 68.6205 69.3100 84.300 100
f2b()
是最快但也不正确的; f1()
目前似乎既快又快(虽然速度对于手头的任务并不重要)并且正确。
答案 1 :(得分:1)
正如弗兰克所指出的,通常最好避免循环。你可以这样轻松地做到这一点:
word <-"Word"
y <-"d"
sum(unlist(strsplit(word,""))==y)
[1] 1
答案 2 :(得分:0)
在不使用for
循环的情况下执行此操作的另一种方法是使用table
函数,该函数返回指定的频率向量。您还需要在使用strsplit
后取消列出,因为它会返回一个列表。最后,我使用了函数tolower
,以防万一字符串与大写字母一起使用(例如,&#34; Banana&#34;转换为&#34; banana&#34;)
freq <- function(x,y) {
word <- tolower(unlist(strsplit(x,"")))
word_table <- table(word)
ans <- word_table[names(word_table)==y]
return(ans)
}
freq("mississippi", "s")
返回
s
4
请注意,这仅在提供单个单词时有效,如果将一串单词添加到x
,则需要对该函数进行推广以单独返回每个单词的频率。
答案 3 :(得分:0)
我不知道这是否是你需要用strsplit()做的事情。如果不是:
x <- "c"
y <- "confluence is crazy cc"
count_string <- function(x,y){
count <- if(unlist(gregexpr(x,y))[1] == -1) 0 else length(unlist(gregexpr(x,y)))
return(count)
}
> count_string(x,y)
[1] 5
> count_string("xx",y)
[1] 0
gregexpr()返回它在列表中找到的每个匹配项的位置位置。如果未找到匹配,则返回-1。我们统计列表以返回它在字符串中匹配的次数。
答案 4 :(得分:0)
逻辑都看起来正确。所以有些东西没有做你想象的那样。
在您的控制台中查看word[i]
。这是一个清单。第一个元素描述类型,第二个值。所以你要将数组与字母进行比较。
Browse[2]> word <- strsplit("something",'')
Browse[2]> word[0]
list()
Browse[2]> word[1]
[[1]]
[1] "s" "o" "m" "e" "t" "h" "i" "n" "g"
现在在R(Matlab,其他数据语言)中,不鼓励使用循环。相反,你应该使用R函数来查看列表。查看函数table - 它使用一种函数方法将比较发送到函数:
frequency <- function(x,y)
{
word <- strsplit(x,'')
val <- table(word[1] == y)["TRUE"]
cat(val)
}
frequency("hih","h")
然后
Browse[2]> frequency("hih","h")
2
答案 5 :(得分:0)
mf <- function(x, y){
count <- table(strsplit(x, '')[[1]])
count[names(count) == y]
}
mf('hello world', 'l')
# l
# 3