使用Ruby的array.index()方法使用通配符搜索数组

时间:2014-12-05 21:32:40

标签: ruby arrays wildcard

我为游戏板创建了一系列瓷砖。我的数组的每个元素都是一个散列,格式如下:

{'x' => x, 'y' => y, 'base' => "base"}

'base'的值可以是任何没有空格的字符串。

我想根据图块的X / Y值找到任何特定图块的索引,而不管图块的基值。

我对如何实现这一点的第一个想法是使用index()方法搜索数组的内容,如下所示:

active_tile = tile.index({'x' => 3, ''y' => 2, 'base' => "WILDCARD_HERE" })

但是,我不知道如何为此实现通配符。任何建议将不胜感激。

如果有人知道我使用的方法肯定不是一个有效的方法,我也会感谢有关更好的存储和检索方法的建议。

为了完整性,这里是我正在使用的整段代码:

class Map
  attr_reader :max_ns   # maximum north-south size
  attr_reader :max_ew   # maximum east-west size
  attr_reader :tile     # the array of tiles

  def initialize(tall, wide)
    @max_ns = tall
    @max_ew = wide

    # Create an array of tiles with X/Y coordinates and a tile base type.
    @tile = []
    (1..tall).each do |y|
      (1..wide).each do |x|
        @tile.push({'x' => x, 'y' => y, 'base' => "ocean"})
      end
    end

    # Pick a spot to start a continent.
    rand_y = rand(3..tall - 2)
    rand_x = rand(3..wide - 2)
    continental_base = @tile.index({'x' => rand_x, 'y' => rand_y, 'base' => "ocean"})
    @tile[continental_base]['base'] = "land"

    # Now spiral around that spot, creating a larger land mass
    # finish writing the function to grab the array indices of the tile's neighbors first.
  end

  # Function to find the array indices of the tiles neighboring any given tile.
  def tile_neighbors(x, y)
    # First get the index of the tile with the given X & Y coordinates.
    cur_tile = @tile.index({'x' => x, 'y' => y, 'base' => "/\A(...)\z/"})
  end
end

3 个答案:

答案 0 :(得分:1)

是的,使用Array#index是明智的:

arr = [{x: 1, y: 2, base: "Yo, how ya' doin'?"},
       {x: 1, y: 3, base: "Hey, bro!"},
       {x: 2, y: 5, z: 4 }]

target = { x: 1, y: 2 }
arr.index { |h| h.values_at(*target.keys) == target.values } #=> 0

target = { x: 1, y: 3 }
arr.index { |h| h.values_at(*target.keys) == target.values } #=> 1

target = { y: 5, x: 2 }
arr.index { |h| h.values_at(*target.keys) == target.values } #=> 2

target = { x: 2, y: 'cat' }
arr.index { |h| h.values_at(*target.keys) == target.values } #=> nil

答案 1 :(得分:0)

首先,使用您当前的数据结构的解决方案。当您使用常规参数调用index时,它会进行精确匹配,因此无效。但是如果你传递,那么它将返回块返回true的第一个元素的索引:

cur_tile = @tile.index { |tile| tile['x'] == x && tile['y'] == y }

但是,我不确定为什么你不会只使用二维数组的tile,其中xy是数组的索引,因此@tiles[0][0]是x和y均为0的那个:

[  [ base00, base01, base02, ... ],
   [ base10, base11, base12, ... ] ]

答案 2 :(得分:0)

  

我想根据图块的X / Y值找到任何特定图块的索引,而不管图块的基值。

那么,让自己轻松一点,根据他们的X / Y值创建所有图块的哈希:

array = [
  {'x' => 1, 'y' => 1, 'base' => "asdf"},
  {'x' => 2, 'y' => 1, 'base' => "sdfg"},
  {'x' => 1, 'y' => 2, 'base' => "dfgh"},
  {'x' => 2, 'y' => 2, 'base' => "fghj"}
]

hash = array.map{ |h| ['%i/%i' % [ h['x'], h['y'] ], h] }.to_h
hash 
# => {"1/1"=>{"x"=>1, "y"=>1, "base"=>"asdf"},
#     "2/1"=>{"x"=>2, "y"=>1, "base"=>"sdfg"},
#     "1/2"=>{"x"=>1, "y"=>2, "base"=>"dfgh"},
#     "2/2"=>{"x"=>2, "y"=>2, "base"=>"fghj"}}

根据X / Y坐标找到一个哈希突然变得容易:

hash['1/1'] # => {"x"=>1, "y"=>1, "base"=>"asdf"}

如果您想快速搜索碱基,可以轻松创建类似的哈希:

hash = array.map{ |h| [h['base'], h] }.to_h
hash 
# => {"asdf"=>{"x"=>1, "y"=>1, "base"=>"asdf"},
#     "sdfg"=>{"x"=>2, "y"=>1, "base"=>"sdfg"},
#     "dfgh"=>{"x"=>1, "y"=>2, "base"=>"dfgh"},
#     "fghj"=>{"x"=>2, "y"=>2, "base"=>"fghj"}}
hash['asdf'] # => {"x"=>1, "y"=>1, "base"=>"asdf"}

并且,只要没有关键的冲突,就没有任何东西可以说两者不能都是同一个大哈希的一部分:

hash1 = array.map{ |h| ['%i/%i' % [ h['x'], h['y'] ], h] }.to_h
hash2 = array.map{ |h| [h['base'], h] }.to_h
hash = hash1.merge(hash2) 
# => {"1/1"=>{"x"=>1, "y"=>1, "base"=>"asdf"},
#     "2/1"=>{"x"=>2, "y"=>1, "base"=>"sdfg"},
#     "1/2"=>{"x"=>1, "y"=>2, "base"=>"dfgh"},
#     "2/2"=>{"x"=>2, "y"=>2, "base"=>"fghj"},
#     "asdf"=>{"x"=>1, "y"=>1, "base"=>"asdf"},
#     "sdfg"=>{"x"=>2, "y"=>1, "base"=>"sdfg"},
#     "dfgh"=>{"x"=>1, "y"=>2, "base"=>"dfgh"},
#     "fghj"=>{"x"=>2, "y"=>2, "base"=>"fghj"}}
hash['1/1'] # => {"x"=>1, "y"=>1, "base"=>"asdf"}
hash['asdf'] # => {"x"=>1, "y"=>1, "base"=>"asdf"}

很容易找到与模式匹配的所有瓷砖:

hash.values_at(*hash.keys.grep(/^a/)) # => [{"x"=>1, "y"=>1, "base"=>"asdf"}]
hash.values_at(*hash.keys.grep(/h$/)) # => [{"x"=>1, "y"=>2, "base"=>"dfgh"}]
hash.values_at(*hash.keys.grep(/dfg/)) # => [{"x"=>2, "y"=>1, "base"=>"sdfg"}, {"x"=>1, "y"=>2, "base"=>"dfgh"}]

或:

hash.values_at(*hash.keys.grep(%r#^1/#)) # => [{"x"=>1, "y"=>1, "base"=>"asdf"}, {"x"=>1, "y"=>2, "base"=>"dfgh"}]
hash.values_at(*hash.keys.grep(%r#/2$#)) # => [{"x"=>1, "y"=>2, "base"=>"dfgh"}, {"x"=>2, "y"=>2, "base"=>"fghj"}]

使用散列的最大优点是它非常快。无论您是想要电路板上的第一块,最后一块还是其他任何一块,查找速度都一样快。数组对于保存你想要按顺序处理的东西很有用,但是当你想快速找到它们时它们很糟糕,但这就是Hashes有用的地方。