简体   繁体   English

私有方法,称为noMethodError ruby

[英]private method called noMethodError ruby

I've been trying to work the following problem out and ran into the error. 我一直在尝试解决以下问题并遇到错误。 The point of the problem is to use a given key sequence to encrypt a string. 问题的关键是使用给定的密钥序列来加密字符串。 For example, when given "cat" and [1,2,3] the result should be "dcw" Any suggestions? 例如,当给定“ cat”和[1,2,3]时,结果应为“ dcw”。有什么建议吗? the error was the following 错误是以下

def vigenere_cipher(string, key_sequence)
  keyIndex=0
  string=string.each_char.map do |c|
    c=c.shift!(c,keyIndex)
    keyIndex+=1
    if keyIndex=key_sequence.length
      keyIndex=0
    end
  end
  return string
end

def shift!(c,keyIndex)
  alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
  inititalLetterIndex=alphabet.index(c)
  finalLetterIndex=alphabet[inititalLetterIndex+keyIndex]
  return alphabet[finalLetterIndex]
end

vigenere_cipher("cat", [1,2,3])
# private method `shift!' called for "c":String (NoMethodError)

You are trying to call shift! 您正在尝试打电话给shift! on string object that does not define on String Class, instead you defined on main object. 在未在String类上定义的字符串对象上,而是在主对象上定义。 You can call it like shift!(c,keyIndex) instead of c.shift!(c,keyIndex) 您可以像shift!(c,keyIndex)那样调用它shift!(c,keyIndex)而不是c.shift!(c,keyIndex)

If you want to call you method shift! 如果您想调用方法shift! on a string, you will have to define it on String class. 在字符串上,您将必须在String类上对其进行定义。

class String
  def shift!(keyIndex)
    # you can access `c` using `self` here
    ...
  end
end

Then you can call it as c.shift!(keyIndex) (Note the arguments are different). 然后,您可以将其称为c.shift!(keyIndex) (注意参数是不同的)。

Step 1 第1步

cipher.rb:4:in `block in vigenere_cipher': private method `shift!' called for "c":String (NoMethodError)

shift! isn't defined in String class, but at the top level. 不是在String类中定义的,而是在顶层定义的。 So replace c=c.shift!(c,keyIndex) by c=shift!(c,keyIndex) 因此,将c=c.shift!(c,keyIndex)替换为c=shift!(c,keyIndex)

Step 2 第2步

cipher.rb:17:in `[]': no implicit conversion of String into Integer (TypeError)

Line 16 defines : 第16行定义:

finalLetterIndex=alphabet[inititalLetterIndex+keyIndex]

alphabet contains letters as Strings, so finalLetterIndex isn't an index (Numeric), but a String. 字母包含作为字符串的字母,因此finalLetterIndex不是索引(数字),而是字符串。

On line 17, you try to use this String as an index. 在第17行,您尝试使用此String作为索引。

Replace line 16 with : 将第16行替换为:

finalLetterIndex=inititalLetterIndex+keyIndex

Step 3 第三步

Your script doesn't raise any exception anymore. 您的脚本不再引发任何异常。 It also doesn't display anything, so add a puts to the last line : 它也不显示任何内容,因此在最后一行添加一个puts:

puts vigenere_cipher("cat", [1,2,3]).inspect

It returns : 它返回:

[0, 0, 0]

Step 4 第四步

keyIndex seems to be stuck at 0. Why? keyIndex似乎停留在0。为什么? Look at line 6 : 看第6行:

if keyIndex=key_sequence.length

It doesn't test an equality, it assigns keyIndex to key_sequence.length . 它不测试相等性,而是将keyIndex分配给key_sequence.length Since any number is truthy in Ruby, it executes the code inside the if statement. 由于任何数字在Ruby中都是真实的,因此它将在if语句中执行代码。 Replace with 用。。。来代替

if keyIndex==key_sequence.length

Step 5 第5步

Your code returns [nil, nil, 0] . 您的代码返回[nil, nil, 0] Why? 为什么?

string is defined as the result of map . string定义为map的结果。 map returns an Array, in which each element is the result of the last executed command inside the block : in this case, the if statement. map返回一个Array,其中每个元素都是该块内最后执行的命令的结果:在本例中为if语句。

if returns nil when the condition isn't satisfied, and returns the last executed command otherwise. if不满足条件, if返回nil ,否则返回最后执行的命令。 In this case 0 . 在这种情况下为0

Add c at the last line of your map block. 添加c在你的最后一行map块。

Step 6 第6步

Your code now returns ["c", "b", "v"] . 您的代码现在返回["c", "b", "v"] Why? 为什么?

You only shift by shiftIndex , not by the amount defined in key_sequence Array. 您只能移动shiftIndex ,而不移动key_sequence Array中定义的数量。 Replace 更换

c=shift!(c,keyIndex)

with

c=shift!(c,key_sequence[keyIndex])

Step 7 步骤7

Your code returns ["d", "c", "w"] . 您的代码返回["d", "c", "w"] Almost there! 快好了!

Ruby is a dynamic language. Ruby是一种动态语言。 You're free to overwrite the String string with an Array, but it will confuse others and your future self. 您可以随意使用Array覆盖String string ,但这会混淆其他人和您未来的自我。

Use array or letters instead of string , and return letters.join 使用arrayletters代替string ,并返回letters.join

Your script now returns "dcw" . 您的脚本现在返回"dcw"

It should look like : 它应该看起来像:

def vigenere_cipher(string, key_sequence)
  keyIndex=0
  letters=string.each_char.map do |c|
    c=shift!(c,key_sequence[keyIndex])
    keyIndex+=1
    if keyIndex==key_sequence.length
      keyIndex=0
    end
    c
  end
  return letters.join
end

def shift!(c,keyIndex)
  alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
  inititalLetterIndex=alphabet.index(c)
  finalLetterIndex=inititalLetterIndex+keyIndex
  return alphabet[finalLetterIndex]
end

Step 8 步骤8

vigenere_cipher("Hello", [1,2,3])

raises 加薪

cipher.rb:17:in 'shift!': undefined method '+' for nil:NilClass (NoMethodError) . cipher.rb:17:in 'shift!': undefined method '+' for nil:NilClass (NoMethodError)

Well, 'H' isn't found in your alphabet. 好吧,在您的字母中找不到'H'。 Use downcase : 使用小写:

array=string.downcase.each_char.map do |c|

Step 9 步骤9

vigenere_cipher("Hello World", [1,2,3])

doesn't work either, because of the space. 由于空间原因,也不起作用。 Delete anything that isn't a letter : 删除所有不是字母的内容:

array=string.downcase.delete('^a-z').each_char.map do |c|

Step 10 第10步

vigenere_cipher("zzz", [1,2,3])

returns an empty String, because there's no letter after z . 返回一个空字符串,因为z后面没有字母。

Use modulo 26 : 使用模26:

return alphabet[finalLetterIndex%26]

Step 11 步骤11

Remove typos, don't use camelCase for variables, remove unnecessary return and you get : 删除错别字,不要使用camelCase作为变量,删除不必要的return ,您会得到:

def vigenere_cipher(string, key_sequence)
  key_index = 0
  letters = string.downcase.delete('^a-z').each_char.map do |c|
    c = shift(c, key_sequence[key_index])
    key_index = (key_index + 1) % key_sequence.length
    c
  end
  letters.join
end

def shift(c, key_index)
  alphabet = ('a'..'z').to_a
  initial_letter_index = alphabet.index(c)
  final_letter_index = initial_letter_index + key_index
  alphabet[final_letter_index % 26]
end

Step 12 步骤12

Using each_char , zip and cycle , I'd rewrite the whole code this way : 使用each_charzipcycle ,我可以这样重写整个代码:

class Integer
  # 0 => 'a', 1 => 'b', ..., 25 => 'z', 26 => 'a'
  def to_letter
    ('a'.ord + self % 26).chr
  end
end

class String
  # 'A' => '0', 'a' => 0, ..., 'z' => 25
  def to_code
    self.downcase.ord - 'a'.ord
  end
end

def vigenere_cipher(string, key)
  short_string = string.delete('^A-Za-z')
  short_string.each_char.zip(key.cycle).map do |char, shift|
    (char.to_code + shift).to_letter
  end.join
end

Step 13 步骤13

Wikipedia article uses a String as key : Wikipedia 文章使用String作为键:

def vigenere_cipher(string, key)
  short_string = string.delete('^A-Za-z')
  short_string.each_char.zip(key.each_char.cycle).map do |char, shift|
    (char.to_code + shift.to_code).to_letter
  end.join
end

vigenere_cipher('Attack at dawn!', 'LEMON').upcase # => "LXFOPVEFRNHR"

Step 14 步骤14

You should also be able to decrypt the message : 您还应该能够解密消息:

def vigenere_cipher(string, key, decrypt = false)
  short_string = string.delete('^A-Za-z')
  short_string.each_char.zip(key.each_char.cycle).map do |char, shift|
    (char.to_code + shift.to_code * (decrypt ? -1 : 1)).to_letter
  end.join
end

vigenere_cipher("LXFOPVEFRNHR", 'LEMON', :decrypt) #=> "attackatdawn"

Well, that was longer than expected! 好吧,那比预期的要长! :D :D

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

相关问题 私有方法`select'调用了nil:NilClass(NoMethodError) - private method `select' called for nil:NilClass (NoMethodError) 私有方法`split'调用了nil:NilClass(NoMethodError) - private method `split' called for nil:NilClass (NoMethodError) 私有方法'eval'调用了Math:Module(NoMethodError) - private method 'eval' called for Math:Module (NoMethodError) 私有方法“ chomp”调用了nil:NilClass(NoMethodError) - private method `chomp' called for nil:NilClass (NoMethodError) 私有方法“ puts”需要“ string”:String(NoMethodError) - private method `puts' called for “string”:String (NoMethodError) 私有方法`puts'调用nil:NilClass(NoMethodError) - private method `puts' called for nil:NilClass (NoMethodError) `map!':调用String的私有方法(NoMethodError) - `map!': private method called for String (NoMethodError) Ruby 2.1:组成零件自行车->调用nil:NilClass的私有方法“ select”(NoMethodError) - Ruby 2.1: Composing a Bicycle of Parts -> private method `select' called for nil:NilClass (NoMethodError) Ruby:调用3:Fixnum的私有方法 - Ruby: Private method called for 3:Fixnum 调用Refinery :: Admin :: PagesController:Class的私有方法“ prepend”(NoMethodError) - private method `prepend' called for Refinery::Admin::PagesController:Class (NoMethodError)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM