繁体   English   中英

仅当在array.each块中使用print语句时才会出现Ruby错误

[英]Ruby bug appears only when using print statements inside a block for array.each

如果我在irb中调用下面的函数anagrams则会得到一个非空的哈希容器,与预期的一样。 但是,如果您注释掉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

我安装了以下版本的rubyirb

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

您的问题是,您在使用elsif表示else含义。 这个:

elsif
    print "No Key\n"
    aHash[aKey] = [el]

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

elsif(print "No Key\n")
    aHash[aKey] = [el]

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

elsif(nil)
    aHash[aKey] = [el]

并且nil在布尔上下文中为false,因此aHash[aKey] = [el]不会发生。 如果删除print则结果如下:

elsif(aHash[aKey] = [el])

并进行分配; 该赋值在布尔上下文中也是正确的(因为Array是),但在这种情况下,真实性无关紧要。

您要在此处使用else

if aHash.key?(aKey)
    aHash[aKey] << el
else
    aHash[aKey] = [el]
end

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

aHash = Hash.new { |h, k| h[k] = [ ] }

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

list.each do |el|
    aKey = el.downcase.chars.sort.to_a.hash
    aHash[aKey] << el
end

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

list.each { |el| aHash[el.downcase.chars.sort] << el }

有人可能会抱怨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

您还可以使用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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM