Ruby:在不使用.uniq的情况下消除数组中的重复项

时间:2013-11-04 23:09:21

标签: ruby arrays

我有一个包含

的数组

arrTV = ['Thor: The Dark World', 'Ender's Game', 'Jackass Presents: Bad Grandpa', 'Last Vegas', 'Free Birds', 'Free Birds' ]

最后两个元素是重复的。我想遍历数组并检查是否存在重复,我不想使用.uniq

请咨询

我尝试了类似这样的东西并且不起作用

arrTV.each do |i|
  count = 0

  #if arrTV[i] == arrTV[i+1]
  #  puts "equal"
  #  count = count + 1
  #
  #end
  #puts count

  #if arrTV[i] = arrTV[i+1]
  #arrTV.delete_at(i+1)
  #end

end

我哪里错了?

6 个答案:

答案 0 :(得分:3)

这可能不是最有效的,但很容易从高层次理解正在发生的事情。

require 'set'

arrTV = ['Thor: The Dark World', 'Ender's Game', 'Jackass Presents: Bad Grandpa', 'Last Vegas', 'Free Birds', 'Free Birds' ]

arrTV.to_set.to_a

答案 1 :(得分:1)

你可以这样做:

arr = []
arrTV.each do |e|
     arr << e unless arr.include?(e)
end
#arr should now contains the same elements as arrTV.uniq does.

但是,为什么不使用uniq?家庭作业可能吗?

答案 2 :(得分:1)

如果您不想使用Array#|方法,我认为您可以使用Array#uniq方法。

arr = %w(foo bar baz bar)
(arr | arr)
# => ["foo", "bar", "baz"]

答案 3 :(得分:0)

怎么样:

2.0.0-p247 :004 > arrTV = ['Thor: The Dark World', 'Ender\'s Game', 
'Jackass Presents: Bad Grandpa', 'Last Vegas', 'Free Birds', 'Free Birds' ]  
# (Note escaping the `'` in Ender`'`s)

2.0.0-p247 :009 > prev='xxxxx'
2.0.0-p247 :009 > new_array=[]

2.0.0-p247 :016 > arrTV.sort.each do |current|
2.0.0-p247 :017 >     if (current != prev)
2.0.0-p247 :018?>       new_array << current
2.0.0-p247 :018?>       puts current
2.0.0-p247 :019?>       prev=current
2.0.0-p247 :020?>     end
2.0.0-p247 :021?>   end
Ender's Game
Free Birds
Jackass Presents: Bad Grandpa
Last Vegas
Thor: The Dark World

答案 4 :(得分:0)

我的发言仅限于你的最后一句话:“我哪里出错?”

arrTV = ['Thor: The Dark World', 'Ender's Game', 'Jackass Presents: Bad Grandpa', \
         'Last Vegas', 'Free Birds', 'Free Birds' ]

[编辑:正如@Michael指出的那样,必须转义arrTV元素中的所有撇号(特别是'Ender\'s Game')。或者,您可以将字符串括在双引号中:

arrTV = ["Thor: The Dark World", "Ender's Game", "Jackass Presents: Bad Grandpa", \
         "Last Vegas", "Free Birds", "Free Birds" ]

我建议做后者。编辑结束]

看来你是第一次尝试这个:

arrTV.each do |i|
  count = 0
  if arrTV[i] == arrTV[i+1]
    puts "equal"
    count = count + 1
  end
  puts count
end

第一次通过(do..end)块时,i设置为arrTV的第一个元素,即'Thor: The Dark World',因此您尝试执行

  if arrTV['Thor: The Dark World'] == arrTV['Thor: The Dark World'+1]

会引发错误。考虑这样做

  if arrTV[count] == arrTV[count+1]

更好,但仍有一些问题。首先,每次将块传递给arrTV元素时,count都会重置为零。您可以在count = 0之前移动arrTV.delete_at(i+1)来解决此问题。另外,将puts count移至if语句的末尾(end之前)。

其次,count = 5时会发生什么?那时你正在执行

  if arrTV[5] == arrTV[6],

arrTV仅包含6个元素,最后一个元素已编入索引5arrTV[6]未定义。有很多方法可以解决这个问题。一个是添加:

  break if count == 5

  count = count + 1

看起来您接下来试图在块中执行此操作

   if arrTV[i] = arrTV[i+1]
   arrTV.delete_at(i+1)

(顺便提一下,请注意您在第一个语句中需要==,而不是=。)即使我们用count替换i,您也试图删除{{{{}}的某些元素1}}同时对它进行交流。这是禁忌。你需要做的是从这开始:

arrTV

有了这个,你不再需要 (0..arrTV.size-2) each do |i| 。一旦处理了count的倒数第二个元素,你也不需要摆脱循环。更重要的是,既然你没有迭代arrTV的元素,你可以在循环中删除它们:

arrTV

(这样,您也可以向 arrTV.delete_at(i+1) 添加元素,或者修改元素。)我将留给您修复它。但是,我想指出,如果它们是arrTV的相邻元素,那么您所采用的方法只会消除重复。如果订单不重要,您需要修改您的方法。

最后,一个Ruby约定是仅使用小写字母表示变量名称,并在必要时添加下划线以提高可读性。您可以使用arrTV之类的内容,而不是arr_tv

答案 5 :(得分:0)

您可以将“设置交点”方法与“&”(&)运算符一起使用:

arrTV = ['Thor: The Dark World', 'Ender\'s Game', 
'Jackass Presents: Bad Grandpa', 'Last Vegas', 'Free Birds', 'Free Birds' ] 

def unique(array)
  array & array
end

result = unique(arrTV)
print result # => ["Thor: The Dark World", "Ender's Game", "Jackass Presents: Bad Grandpa", "Last Vegas", "Free Birds"]

使用Set Intersection(使用相交运算符&),将返回一个新数组,其中包含两个数组共有的元素,并删除了重复项。

在该方法中,&位于我们要评估的两个数组之间。在这个例子中,我们将一个数组传递给方法,但是根据它自己评估该数组以删除任何重复数据。