只有在array.each中使用块内的print语句时才会出现Ruby错误

nis*_*sah 0 ruby arrays hash

如果我anagramsirb中调用下面的函数,我会得到一个非空的哈希容器.但是如果您注释掉该print "No Key\n"行,则返回的哈希容器现在为空.事实上,对于列表中的所有元素,elsif分支中的代码似乎都在执行.要么我疯了,要么这里有一个讨厌的错误:

def anagrams(list = ['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams', 'scream'])
        aHash = Hash.new()
        list.each { |el|
            aKey = el.downcase.chars.sort.to_a.hash
            if aHash.key?(aKey)
                # print "Has Key\n"
                aHash[aKey] << el
            elsif
                # print "No Key\n"
                aHash[aKey] = [el]
            end
        }

        return aHash
end
Run Code Online (Sandbox Code Playgroud)

我安装了以下版本的rubyirb:

ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]
irb 0.9.6(09/06/30)
Run Code Online (Sandbox Code Playgroud)

mu *_*ort 6

你的问题是,你正在使用elsif你的意思else.这个:

elsif
    print "No Key\n"
    aHash[aKey] = [el]
Run Code Online (Sandbox Code Playgroud)

是误导性的格式,它实际上解释更像这样:

elsif(print "No Key\n")
    aHash[aKey] = [el]
Run Code Online (Sandbox Code Playgroud)

print返回nil所以逻辑是这样的:

elsif(nil)
    aHash[aKey] = [el]
Run Code Online (Sandbox Code Playgroud)

并且nil在布尔上下文中为false,因此aHash[aKey] = [el]永远不会发生.如果你删除了print那么你最终得到这个:

elsif(aHash[aKey] = [el])
Run Code Online (Sandbox Code Playgroud)

并且分配发生; 在布尔上下文中也是如此(因为数组是),但在这种情况下,真实性是无关紧要的.

你想在else这里使用:

if aHash.key?(aKey)
    aHash[aKey] << el
else
    aHash[aKey] = [el]
end
Run Code Online (Sandbox Code Playgroud)

更好的方法是使用带有数组的Hash(通过块)作为其默认值:

aHash = Hash.new { |h, k| h[k] = [ ] }
Run Code Online (Sandbox Code Playgroud)

然后你根本不需要它if,你可以这样做:

list.each do |el|
    aKey = el.downcase.chars.sort.to_a.hash
    aHash[aKey] << el
end
Run Code Online (Sandbox Code Playgroud)

而且你可以使用任何东西作为Ruby Hash中的键,所以你甚至不需要.to_a.hash,你可以简单地使用Array本身作为键; 此外,sort将为您提供一个数组,所以你甚至不需要to_a:

list.each { |el| aHash[el.downcase.chars.sort] << el }
Run Code Online (Sandbox Code Playgroud)

有人可能会抱怨return你的方法结束,所以我会这样做:你不需要return方法的末尾,只是说aHash,它将是方法的返回值:

def anagrams(list = ['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams', 'scream'])
    aHash = Hash.new { |h, k| h[k] = [ ] }
    list.each { |el| aHash[el.downcase.chars.sort] << el }
    aHash
end
Run Code Online (Sandbox Code Playgroud)

您还可以使用each_with_object它来压缩它:

def anagrams(list = ['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams', 'scream'])
    list.each_with_object(Hash.new { |h, k| h[k] = [ ] }) do |el, h|
        h[el.downcase.chars.sort] << el
    end
end
Run Code Online (Sandbox Code Playgroud)

但我可能会这样做,以减少噪音:

def anagrams(list = ['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams', 'scream'])
    h = Hash.new { |h, k| h[k] = [ ] }
    list.each_with_object(h) { |el, h| h[el.downcase.chars.sort] << el }
end
Run Code Online (Sandbox Code Playgroud)