如何计算ruby中另一个字符串中字符串元素的出现次数?

时间:2016-09-23 18:07:53

标签: ruby string

如何查看字符串中出现短语的次数?

例如,假设短语为donut

str1 = "I love donuts!"
#=> returns 1 because "donuts" is found once.
str2 = "Squirrels do love nuts" 
#=> also returns 1 because of 'do' and 'nuts' make up donut
str3 = "donuts do stun me" 
#=> returns 2 because 'donuts' and 'do stun' has all elements to make 'donuts'

我检查了this SO建议使用include,但只有在donuts按顺序拼写时才有效。

我想出了这个,但是在"donuts"的所有元素拼写完成后它不会停止拼写。即"I love donuts" #=> ["o", "d", "o", "n", "u", "t", "s"]

def word(arr)
  acceptable_word = "donuts".chars
  arr.chars.select { |name| acceptable_word.include? name.downcase }
end

如何查看给定字符串中出现donuts的次数?没有边缘情况。输入将始终为String,不会为零。如果它包含donut的元素,则不应计为1次;它需要包含donuts,不必按顺序排列。

4 个答案:

答案 0 :(得分:4)

<强>代码

def count_em(str, target)
  target.chars.uniq.map { |c| str.count(c)/target.count(c) }.min
end

<强>实施例

count_em "I love donuts!", "donuts"                      #=> 1
count_em "Squirrels do love nuts", "donuts"              #=> 1
count_em "donuts do stun me", "donuts"                   #=> 2
count_em "donuts and nuts sound too delicious", "donuts" #=> 3
count_em "cats have nine lives", "donuts"                #=> 0
count_em "feeding force scout", "coffee"                 #=> 1
count_em "feeding or scout", "coffee"                    #=> 0

str = ("free mocha".chars*4).shuffle.join
  # => "hhrefemcfeaheomeccrmcre eef oa ofrmoaha "
count_em str, "free mocha"
  #=> 4

<强>解释

有关

str = "feeding force scout"
target = "coffee"

a = target.chars
  #=> ["c", "o", "f", "f", "e", "e"] 
b = a.uniq
  #=> ["c", "o", "f", "e"] 
c = b.map { |c| str.count(c)/target.count(c) }
  #=> [2, 2, 1, 1] 
c.min
  #=> 1 

在计算c时,请考虑传递给块的b的第一个元素,并将其分配给块变量c

c = "c"

然后块计算

d = str.count(c)
  #=> 2 
e = target.count(c)
  #=> 1
d/e
  #=> 2

这表示str包含足够的"c"以匹配“咖啡”两次。

获得c的其余计算是相似的。

<强>附录

如果str匹配字符target的字符必须与target的字符顺序相同,则可以使用以下正则表达式。

target = "coffee"

r = /#{ target.chars.join(".*?") }/i
  #=> /c.*?o.*?f.*?f.*?e.*?e/i

matches = "xcorr fzefe yecaof tfe erg eeffoc".scan(r)
  #=> ["corr fzefe ye", "caof tfe e"]
matches.size
  #=> 2

"feeding force scout".scan(r).size
  #=> 0 

需要正则表达式中的问号才能使搜索变得非贪婪。

答案 1 :(得分:2)

解决方案或多或少简单(map(&:dup)用于避免输入变异):

pattern = 'donuts'
[str1, str2, str3].map(&:dup).map do |s|
  loop.with_index do |_, i|
    break i unless pattern.chars.all? { |c| s.sub!(c, '') }
  end
end
#⇒ [1, 1, 2]

答案 2 :(得分:1)

这是一种有两种变体的方法,一种是字母必须按顺序出现,另一种是顺序无关紧要。在这两种情况下,每个字母的频率都得到尊重,因此“咖啡”必须匹配两个“f”和两个“e”字母,“免费摩卡”不足以匹配,缺少第二个“f”。

def sorted_string(string)
  string.split('').sort.join
end

def phrase_regexp_sequence(phrase)
  Regexp.new(
    phrase.downcase.split('').join('.*')
  )
end

def phrase_regexp_unordered(phrase)
  Regexp.new(
    phrase.downcase.gsub(/\W/, '').split('').sort.chunk_while(&:==).map do |bit|
      "#{bit[0]}{#{bit.length}}"
    end.join('.*')
  )
end

def contains_unordered(phrase, string)
  !!phrase_regexp_unordered(phrase).match(sorted_string(string.downcase))
end

def contains_sequence(phrase, string)
  !!phrase_regexp_sequence(phrase).match(string.downcase)
end

strings = [
  "I love donuts!",
  "Squirrels do love nuts",
  "donuts do stun me",
  "no stunned matches",
]

phrase = 'donut'

strings.each do |string|
  puts '%-30s %s %s' % [
    string,
    contains_unordered(phrase, string),
    contains_sequence(phrase, string)
  ]
end

# => I love donuts!                 true true
# => Squirrels do love nuts         true true
# => donuts do stun me              true true
# => no stunned matches             true false

答案 3 :(得分:0)

简单的解决方案:

criteria = "donuts"
str1 = "I love donuts!"
str2 = "Squirrels do love nuts"
str3 = "donuts do stun me"

def strings_construction(criteria, string)
    unique_criteria_array = criteria.split("").uniq
    my_hash = {}

    # Let's count how many times each character of the string matches a character in the string 
    unique_criteria_array.each do |char|
        my_hash[char] ? my_hash[char] = my_hash[char] + 1 : my_hash[char] = string.count(char)
    end

    my_hash.values.min
end

puts strings_construction(criteria, str1) #=> 1
puts strings_construction(criteria, str2) #=> 1
puts strings_construction(criteria, str3) #=> 2