避免在数组中双重输入项目

时间:2014-12-18 21:20:36

标签: ruby ruby-on-rails-3

我有以下代码可以使用

def add_item!(item, list)
  list << item
  list # this is what we return from the method
end

如果我有物品就行了。

add_item!(2, "henk")
add_item!(3, "george")

但是我想要检查项目是否已经在列表中。我想过用list.include做这个吗?功能。如果我尝试这个我得到

def add_item! (item, list)

  if list.include?(item)
    list << item
    list
  else
    puts "This is a double item"
  end
end

add_item!(2, "list")
add_item!(2, "list")

然而,这会给我带来以下错误:

TypeError: can't convert Fixnum into String

我不明白为什么会这样,可以避免这种情况。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

如果您需要列表,并且不想要重复,那么请不要使用数组,请使用Set

  

Set实现无序值的集合,没有重复项。这是Array直观的互操作设施和Hash快速查找的混合体。

不必担心某些事物是否已存在,您可以将代码保持为:

require 'set'
the_set = [].to_set

def add_item!(item, list)
  list << item
end

add_item!('foo', the_set)
the_set # => #<Set: {"foo"}>
add_item!('bar', the_set)
the_set # => #<Set: {"foo", "bar"}>
add_item!('foo', the_set)
the_set # => #<Set: {"foo", "bar"}>

如果您需要它作为数组,请使用to_a

the_set.to_a # => ["foo", "bar"]

但实际上,不是创建一个真正无法减少代码的方法,只需使用<<

add_item!('foo', the_set)
the_set # => #<Set: {"foo"}>
the_set << 'bar'
the_set # => #<Set: {"foo", "bar"}>

它更短,比调用方法更快。

在我看来,通过将单个操作移动到方法中来干燥代码并不能提供帮助,并且从长远来看可能会使事情变得更糟,因为操作是隐藏的。


  

但是我想要检查项目是否已经在列表中。我想过用list.include做这个吗?功能。如果我尝试这个我得到

if list.include?(item)

仔细查看条件测试。如果if list.include?(item)表示&#34;项目在列表&#34;中,是否要附加到list变量?

答案 1 :(得分:0)

我同意The Tin Man的回答 - Set是保持独特收藏的最佳方式。您的代码引发的异常有什么问题 - 仔细看看您做了什么:

add_item!(2, "henk")

您实际上是将Integer添加到String

'henk' << 2
# => "henk\u0002"

在第二种情况下

add_item!(2, "list")

你完全一样:

"list".include?(2)
TypeError: no implicit conversion of Fixnum into String

因此,您只需将ArraySet传递给您的方法,而不是String

my_array = []
add_item!(2, my_array)

另请仔细查看您的if - 声明

if list.include?(item)
  list << item
  list
else
  puts "This is a double item"
end

如果项目已经存在,那么您将要添加一个项目,这显然不是您想要达到的目标,因此您实际应该使用unless代替if或反过来:

if list.include?(item)
  puts "This is a double item"
else
  list << item
  list
end

另外与Array进行合作,您可以通过

来保持其唯一性
list |= [item]

例如:

my_array = []
# => []
my_array |= [1]
# => [1]
my_array |= [1]
# => [1]