【问题标题】:Using .include? to prevent duplicates使用 .include?防止重复
【发布时间】:2015-10-08 22:42:57
【问题描述】:

对于如何使用.include? 来防止重复项加入列表有点困惑。

我首先被告知要在列表中附加一个项目。

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

然后我需要使用.include? 来防止重复。我的尝试:

def add_item!(item, list)
  list << item
  list.include?(item)
end

【问题讨论】:

标签: ruby


【解决方案1】:

你可以这样使用它:

def add_item!(item, list)
  list << item unless list.include?(item)
end

在上面的代码中,#include? 在将项目添加到列表之前被调用。如果项目已经在列表中,#include? 返回 true,将跳过将项目添加到列表的代码。

【讨论】:

  • 类似的东西也应该可以工作 =>> list |= [item]
  • 我完全忘记了unless。但是它返回 nil 而不是说 orange 作为一个项目。
  • 然后你可以使用 if/else 语句在项目被包含时做一些特别的事情。
  • 提问后请不要添加要求。我提供的代码按要求防止重复。
  • 我只是不知道使用unless 使它返回nil。不打算添加“要求”。
【解决方案2】:

如果你想把代码放在一个方法中,你必须考虑到 Ruby 通过值而不是通过引用来传递参数。为什么在第一种情况下这似乎有效,我不知道,这本身可能是一个问题。所以我用 ! 结束了第一个方法的名称。 (到位)但不是其他两个。

我用三种不同的方法做了一些基准测试,包括?解决方案显然获胜。放置数组的初始值需要时间,但所有解决方案都必须这样做,因此您可以丢弃它。

require 'set'
require 'benchmark'

def add_item1!(item, list)
  list << item unless list.include?(item)
end

def add_item2(item, list)
  list |= [item]
end

def add_item3(item, list)
  set = Set.new(list)
  set << item
  list = set.to_a
end

array1 = [3,2,1,4]
add_item1!(2, array1) # [3, 2, 1, 4]
add_item1!(5, array1) # [3, 2, 1, 4, 5]

array2 = [3,2,1,4]
array2 = add_item2(2, array2) # [3, 2, 1, 4]
array2 = add_item2(5, array2) # [3, 2, 1, 4, 5]

array3 = [3,2,1,4]
array3 = add_item3(2, array3) # [3, 2, 1, 4]
array3 = add_item3(5, array3) # [3, 2, 1, 4, 5]

TESTS = 100000
Benchmark.bmbm do |results|
  results.report("unless not new") {TESTS.times {array1 = [3,2,1,4];add_item1!(2, array1) }}
  results.report("unless new")     {TESTS.times{array1 = [3,2,1,4];add_item1!(5, array1) }}
  results.report("|= not new")     {TESTS.times{array2 = [3,2,1,4];array2 = add_item2(2, array2) }}
  results.report("|= new")         {TESTS.times{array2 = [3,2,1,4];array2 = add_item2(5, array2) }}
  results.report("Set not new")    {TESTS.times{array3 = [3,2,1,4];array3 = add_item3(2, array3) }}
  results.report("Set new")        {TESTS.times{array3 = [3,2,1,4];array3 = add_item3(5, array3) }}
end

#                      user     system      total        real
# unless not new   0.031000   0.000000   0.031000 (  0.027002)
# unless new       0.047000   0.000000   0.047000 (  0.052003)
# |= not new       0.125000   0.000000   0.125000 (  0.118007)
# |= new           0.125000   0.000000   0.125000 (  0.126007)
# Set not new      0.358000   0.000000   0.358000 (  0.354020)
# Set new          0.359000   0.000000   0.359000 (  0.364021)

【讨论】:

  • 感谢接受 rSV,我在stackoverflow.com/questions/31506596/…问了关于通过引用传递的问题
  • 很好的答案,但应该注意的是,如果您将多个项目添加到列表中,您会得到不同的结果。特别是,创建一个集合的设置成本很快就会得到回报。根据应用程序,放弃添加然后uniqifying 可能是另一种可能性。
【解决方案3】:

如果您只想维护您的数组并且您不知道是否添加了元素,您可以这样做

def add_item!(item, list)
  list = list | [item]
end

在这里你可以找到一个例子。

2.2.1 :001 > [1,2]
 => [1, 2] 
2.2.1 :002 > [1,2] | [1]
 => [1, 2] 
2.2.1 :003 > [1,2] | [1,3]
 => [1, 2, 3] 
2.2.1 :004 > 

ary | other_ary → new_ary

Set Union — 通过将 ary 与 other_ary 连接返回一个新数组,排除 > 任何重复项并保留原始数组的顺序。

但是如果你想知道元素是否被拒绝,你可以这样做

def add_item!(item, list)
  list << item unless list.include?(item)
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    相关资源
    最近更新 更多