Arrays Ruby(v2.3.1).split数组上的每个方法不按任何逻辑顺序

Arrays Ruby(v2.3.1).split数组上的每个方法不按任何逻辑顺序,arrays,ruby,string,each,Arrays,Ruby,String,Each,我有一个简单的字符串: 西北东南 我想将其拆分为子字符串,并将其作为子数组放到一个数组中,即: [["direction", "north"], ["direction", "south"], ["direction", "east"], ["direction", "west"]] 但是,每个方法似乎既不能按字母顺序处理元素,也不能按元素输入的顺序处理元素 .each方法似乎按以下顺序处理拆分字符串: 北第一子字符串[按字母顺序第二] 南第三子字符串[按字母顺序第三] 西第二子字符串[按字母

我有一个简单的字符串:

西北东南

我想将其拆分为子字符串,并将其作为子数组放到一个数组中,即:

[["direction", "north"], ["direction", "south"], ["direction", "east"], ["direction", "west"]]
但是,每个方法似乎既不能按字母顺序处理元素,也不能按元素输入的顺序处理元素

.each方法似乎按以下顺序处理拆分字符串:

北第一子字符串[按字母顺序第二] 南第三子字符串[按字母顺序第三] 西第二子字符串[按字母顺序最后一个] east last子字符串[按字母顺序排列的第一个] 它肯定不会按字母顺序遍历子字符串,也不会按相反顺序遍历子字符串,而是从第一个子字符串开始,最后一个子字符串结束,并切换中间的字符串

我就是想不出来

这是我的密码:

class Lexicon

  def scan(stuff)

    words = stuff.split

    #Empty arrays to easily push split words into
    @direction_array = []

    #Lexicons of different kinds of words
    @directions = ["north", "south", "east", "west", "down", "up", "left", "right", "back"]

    puts "This the original set"
    print words, "\n"

    while words.any? == true
      words.each do |word|
        if @directions.include? word
          puts "This is the word I selected: #{word}"
          @direction_array.push(['direction', word])
          words.delete word
          print @direction_array
          puts "This is what remains in the words set: #{words}"
        else
          "This word does not belong."
          words.delete word
          # puts "This is what remains in the words set: #{words}"
        end
      end
    end

    if @direction_array.any? == true
      puts "This is what we have in the direction array:"
      print @direction_array, "\n"
      return @direction_array
    else
      puts "Nothing to show for our efforts"
    end
  end
end

testing = Lexicon.new()
testing.scan("north south east west")

以下是一些关于如何使Ruby更加传统的想法:

class Lexicon
  # Declare things that are repeatedly used without being modified as
  # constants at the class-level.
  DIRECTIONS = %w[ north south east west down up left right back ]

  def scan(stuff)
    # Split the string and select all the words that are present
    # in the DIRECTIONS above.
    stuff.split.select do |word|
      DIRECTIONS.include?(word)
    end.map do |word|
      # Transform these into [ 'direction', x ] pairs
      [ 'direction', word ]
    end
  end
end
如果您将代码组织成整洁、简洁的块,将意图表示为一系列简单的转换,那么代码就变得非常容易理解。注意,这里不需要显式返回,因为默认情况下该操作是隐式返回的

要练习它,您可以获得以下信息:

testing = Lexicon.new
testing.scan("north south east west")
# => [["direction", "north"], ["direction", "south"], ["direction", "east"], ["direction", "west"]]
p方法在显示变量内容方面非常方便,测试任意代码的irb工具也是如此


我认为您的原始代码中的一些问题来自于使用迭代和删除方法,而不是使用拒绝或选择的过滤方法。从您正在积极迭代的数组中删除内容通常会适得其反,而且由于从数组中删除内容实际上在计算上非常昂贵,因此只构建您想要的元素的新数组更容易。

如果从数组中删除元素,然后,删除元素留下的孔右侧的所有元素都向左移动以填充间隙

dirs = "north west south east".split
  #=> ["north", "west", "south", "east"]

["direction"].product(dirs)
  #=> [["direction", "north"], ["direction", "west"],
  #    ["direction", "south"], ["direction", "east"]] 
在数组上迭代时,正在从数组中删除元素。如果您只删除尚未迭代的元素,那就可以了。但是,如果删除一个已经迭代过的元素,则删除元素右侧的所有元素(包括下一个将要迭代的元素)都会向左移动,以填充删除元素留下的洞,从而跳过下一个元素


在对数据结构进行迭代时,您永远不应该对其进行变异,除非明确说明这是一件安全的事情。

您可以采取以下方法:

"north west south east".split.collect { |direction| ['direction', direction] }

将方向拆分为数组的元素,然后按要求收集它们。

最好摆脱添加诸如while x==true或if x==true之类的不必要代码的习惯,因为while x几乎总是能够完成这项工作,特别是在有需要的情况下?将只返回true或false。这比我的代码优雅得多,我将花一些时间确保我理解这一点。谢谢你,没有比这更容易的了。注意:您可以使用拆分定义dir,它将与问题完全匹配。