从哪里删除?

时间:2014-04-20 03:54:52

标签: ruby hash each

下面我写了一段代码,它应该计算字符串中字符出现的次数,并以散列形式显示结果。我的想法是在我计算它之后立即删掉字符串中的那个字母,以便我们不会多次将它放入哈希值。

我的原始代码是:

def letter_count_spec(str)
letter_count = Hash.new #create hash
letter = str.split('') #separate letters
letter.each{ |e|
    if( /[A-Za-z0-9]/.match(e)  )
        occurances = letter.count{ |x| x==e}
        letter_count[e] = occurances
        letter.delete(e) #delete letter 

    end
}        

return letter_count
end

letter_count_spec("cat")

结果:=> {" c" => 1," t" => 1}

我输了" a"!

所以我尝试了这个:

def letter_count_spec(str)
letter_count = Hash.new #create hash
letter = str.split('') #separate letters
letter.each{ |e|
    if( /[A-Za-z0-9]/.match(e)  )
        occurances = letter.count{ |x| x==e}
        letter_count[e] = occurances
    end
}        
letter.each{ |e|
    letter.delete(e) #delete letter
}
    return letter_count
end

letter_count_spec("cat")

result => {" a" => 1," c" => 1," t" => 1}

为什么我需要再次通过数组删除?

1 个答案:

答案 0 :(得分:1)

迭代期间对集合的修改可能会导致问题,这在评论中有说明。

字计数算法通常包括用于跟踪字数的散列,以及用于遍历内容的迭代器。您无需修改​​原始集合。这是一个O(n)解决方案,假设在一般情况下散列的更新复杂度为O(1)。但是,帖子中的计数和删除方法具有O(n ^ 2)复杂度(如果有效)。

def letter_count_spec(str)
  letter_count = Hash.new(0) # create hash, and use 0 as the default value
  letter = str.split('')     # separate letters
  letter.each do |e|
    if /[A-Za-z0-9]/.match(e)
      letter_count[e] += 1   # increment count
    end
  end
  letter_count
end
BTW,在Ruby中,将do ... end用于多行阻塞是一种惯例,除非在某些情况下需要{}