在`items`中搜索`target_item`;返回数组索引

时间:2014-04-28 01:12:57

标签: ruby arrays while-loop

有人可以帮我理解下面的代码吗?我一直在尝试添加'puts'来查看它的功能,但不断出现错误。这是我应该已经知道的练习/示例中的代码,但我不知道它在做什么。在我看来,我应该在方法之前定义一个items数组才有意义,但即便如此,我也无法理解它。

# search for `target_item` in `items`; return the array index
# where it first occurs
def find_item(items, target_item)
  i = 0
  while i < items.count
    current_item = items[i]
    if current_item == target_item
      # found item; return its index; stop here and exit the
      # method
      return i
    end
    i += 1
  end

  # return nil to mean item not found
  nil
end

2 个答案:

答案 0 :(得分:1)

你需要一个数组items来运行你的代码是正确的。您还需要变量target_item的值。这两个变量作为参数传递给方法find_item。如果方法在数组target_item中找到items的值,它将返回数组中该项的索引(第一个元素为0,第二个元素为1,依此类推);如果没有,它将返回nil

如果您在IRB中运行代码,它将返回=> :find_item。这意味着它没有发现任何错误。但这并不意味着没有错误,因为代码运行时可能会出现错误。

让我们尝试一些数据。运行定义方法的代码(在IRB中)后,运行以下三行:

items = ['dog', 'cat', 'pig']
target_item = 'cat'
find_item(items, target_item) #=> 1

其中#=> 1表示该方法返回1,意味着它在target_items的偏移1处找到items,这正是我们所期望的。

这相当于:

find_item(['dog', 'cat', 'pig'], 'cat')

另一方面,

find_item(items, 'bird') #=> nil

因为数组不包含'bird'。两行

current_item = items[i]
if current_item == target_item

可以组合成一个:

if items[i] == target_item

但这不是重点,因为Rubiests不会以这种方式编写方法。相反,你通常会这样做:

def find_item(items, target_item)
  items.each_with_index { |e,i| return i if e == target_item }
  nil
end

[编辑:@Mark正确地指出了一种更简单的编写方法的方法。但是,我会坚持使用这个版本,因为我认为通过查看它的工作原理,你将学到一些有用的东西。]

内置的Ruby方法each_with_index来自Enumgerable模块,它始终可供您使用(以及该模块中定义的60多种其他方法)。引用方法时,最好包括定义它的类或模块。此方法为Enumerable#each_with_index。除此之外,如果你知道它的类或模块,它更容易找到该方法的文档。

虽然在Enumerable模块中定义了each_with_index,但它是一个“枚举器”,这意味着它将items中的值提供给下一个块,由{...}表示(如此处所示) )或do ... end

在IRB中运行:

items = ['dog', 'cat', 'pig']
target_item = 'cat'
enum = items.each_with_index
  #=> #<Enumerator: ["dog", "cat", "pig"]:each_with_index>

您可以将其转换为数组以查看它将为块提供的内容:

enum.to_a
  #=> [["dog", 0], ["cat", 1], ["pig", 2]]

现在考虑将枚举数传递给块的第一个元素:

["dog", 0]

中的块变量ei
  items.each_with_index { |e,i| return i if e == target_item }
因此

将被设置为:

e => "dog"
i => 0

因此,e == target_item变为"dog" == "cat",即false,因此return 0不会被执行。但是,对于下一个项目,

e => "cat"
i => 1

由于"cat" == "cat"truereturn 1已执行,我们已完成。如果items不包含cat,则枚举器将枚举所有项目,控件将转到以下语句nil。由于这是最后执行的语句,该方法将返回nil

答案 1 :(得分:1)

此代码似乎是一个重写不佳的Array#index。这是相同的:

items.index(target_item)