ruby测验 - 使用while循环重新分配数组值

时间:2013-02-21 12:19:12

标签: ruby

我从“简单”的红宝石测验中得到了这个例子。我想重新分配一个数组的值(例如word1 [0]),如果它等于(==)array1的值到array2的值。看看代码,这很明显:

array1 = Array.new
array1 = ('A'..'Z').to_a

array2 = Array.new
array2 = ('A'..'Z').to_a
array2 = array2.rotate(2)

puts "enter a word:"
word1 = gets.chomp
word1 = word1.upcase.split(//)

n = 0

word1.each do
  while n < 26
    if word1[n] == array1[n]
      word1[n] = array2[n]
    end
    n += 1
  end
end

puts word1   # This word should now be "encoded" and not easy to read.

我尝试过这段代码,它只是随机改变了我输入的任何单词的1-2个字母(gets.chomp)。

因此word1是我期待的一个数组,每个元素(字母)都与array1 [0]进行比较,如果它等于那么它将被重新赋值给array2 [0]的值。如果word1 [0]和array1 [0]不相等,那么'n'的值会改变+1,然后再次运行该块。

注意:我不想为这个问题找到一个简单的公式,我想真正理解这里发生了什么以及为什么我的每次迭代都不能像我期望的那样工作。所以,如果你能在“我的知识水平”上回答这个问题那真的很棒!

3 个答案:

答案 0 :(得分:1)

首先,您忘记在连续的单词之间重置计数器N.您将N设置为零,然后开始迭代单词。

所以,在概述中,你的算法就是这样:

首先,N迭代超过0..25
对于第二个单词,N以26开头,并且不进行迭代 对于第三个单词,N以26开头,并且不迭代
.. 等

因此,对于完整的初学者,请执行:

array1 = Array.new
array1 = ('A'..'Z').to_a

array2 = Array.new
array2 = ('A'..'Z').to_a
array2 = array2.rotate(2)

puts "enter a word:"
word1 = gets.chomp
word1 = word1.upcase.split(//)     # <-- note that you REPLACE the input string
                                   # with an sequence of STRINGS produced by SPLIT

word1.each do                      # for each STRING in the SEQUENCE
  n = 0
  while n < 26                     # scan all 26 letters from ARRAY
    if word1[n] == array1[n]       # ... WTF
      word1[n] = array2[n]
    end
    n += 1
  end
end

现在,您将保持字母扫描至少以相同的方式为每个单词运行。但是,这也不会像预期的那样起作用,但完全不同的原因。

你如何实际使用N?

    if word1[n] == array1[n]
      word1[n] = array2[n]
    end

所以,你从SEQUENCE中读到了Nth WORD ..并将它与array1中的Nth LETTER进行比较。

这真的是你想要做的吗?不是。

你很可能想要用WORD中的每个字母替换两个数组形成的字母对。

所以,相反,你想:

  • 阅读WORD1的第N个字母
  • 然后检查在array1
  • 中的索引
  • 然后阅读该索引中的替换字母
  • 然后把信写回WORD的第N个地方:

    letter = word[position]
    letterindex = array1.index(letter)
    substitution = array2[letterindex]
    word[position] = subsitution
    

你也可以将它压缩成oneliner:

 -- loop
    -- loop2
      word[position] = array2[array1.index(word[position])]

但请注意,我现在说position,而不是N。您已使用N作为范围0..25,这意味着ARRAY中字母的索引。

但是,为了检查单词的字母,你需要在单词的字母上重复。这个词有多长?当然,不是0..25!

另请注意微妙的变化:word而不是word1。我说“单词”和“单词的字母”,而不是“arrayofwords”。最初,您还使用N来读取序列中的第N个单词,让我们保留它。但是,由于我们需要迭代单词的leters,需要一个不同的变量,“说position

n = 0

arrayOfWords.each do

    word = arrayOfWords[n]

    position = 0

    while position < word.length
        letter = word[position]
        letterindex = array1.index(letter)
        substitution = array2[letterindex]
        word[position] = subsitution
        position += 1
    end

    n += 1
end

请注意N如何保持并且仅随每个单词增加,以及每次将position重置为零的方式,以迭代当前单词的实际长度

在Ruby中,这是一种过于精细的方式。 Ruby有许多可以缩短代码的好技巧。例如,each方法不仅仅是一个循环。它实际上给你每个单词 *,你根本不需要N:

arrayOfWords.each do |word|

    position = 0

    while position < word.length
       word[position] = array2[array1.index(word[position])]
       position += 1
    end

end

请注意我是如何在条形图中添加“word”的致each电话。 以类似的方式,您实际上也可以摆脱position,但这反过来会使代码更短但更难以阅读/理解。

答案 1 :(得分:0)

我认为问题在于您使用相同的“计数器”n来检查两个不同的数组,请尝试以下方法:

修改 根据你的评论,因为你只需要这么争吵,这是一种可能的方式:

array1 = ('A'..'Z').to_a
array2 = ('A'..'Z').to_a.shuffle

puts "enter a word:"
word1 = gets.chomp
word1 = word1.upcase.split(//)

n = 0

word1.each do
  word1[n] = array2[n]
  n +=1
end

puts word1

由于shuffle

中的array2,即使您使用相同的字词,它也会始终生成不同的输入

答案 2 :(得分:0)

我终于用一个非常简单的方法回答了我的问题:

def cypher(input_array)

  normal_array = ['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']
  cypher_array = normal_array.rotate(2)
  awesome_cyphered_array = []

  input_array.each do |element|
    0.upto(25) do |i|
      case element
        when normal_array[i]
          awesome_cyphered_array << cypher_array[i]
      end
    end
  end
  puts awesome_cyphered_array.join  
end

# START of my program
puts "Enter a sentence, it will be cyphered!"
sentence = gets.chomp
length = sentence.length
sentence_as_array = sentence.upcase.split(//).reverse!

make_it_an_array = []

1.upto(length) do 
  make_it_an_array << sentence_as_array.pop
end

cypher(make_it_an_array)