字符串中的字符频率

时间:2017-04-14 13:47:39

标签: r

我想创建一个带有两个参数的函数,它将显示给定单词中字符的频率: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.这是什么原因?

6 个答案:

答案 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