使用Ruby仅删除数组中的特定重复项

3yhwsihp  于 2023-04-20  发布在  Ruby
关注(0)|答案(4)|浏览(195)

有没有一种方法可以使用Ruby删除数组中的特定重复项?示例数组:

["hello", "removeme", "removeme", "hello", "testing"]

我只想删除该数组上"removeme"的重复项。所需的输出是:

["hello", "removeme", "hello", "testing"]

有没有这样的方法来获得所需的输出?["hello", "removeme", "removeme", "hello", "testing"].uniq('removeme')
先谢谢你了。

fsi0uk1n

fsi0uk1n1#

您可以将uniq与一个块一起使用,该块根据块的返回值删除重复项:

ary = ["hello", "removeme", "removeme", "hello", "testing"]

ary.uniq { |obj| obj.eql?('removeme') || Object.new }
#=> ["hello", "removeme", "hello", "testing"]

对于等于'removeme'的元素,我们返回true,对于其他元素('hello''hello''testing'),我们返回一个新对象:(注意不同的对象ID)

"hello"    → #<Object:0x00007f9ab08590d8>
"removeme" → true
"removeme" → true
"hello"    → #<Object:0x00007f9ab0858d68> 
"testing"  → #<Object:0x00007f9ab08589f8>

所有具有相同返回值的元素都被认为是重复的,即uniq将把'removeme'视为重复的,而其他任何东西都是唯一的,而不管它的实际值如何。这允许两个相同的'hello'字符串保留下来。
除了Object.new,你也可以使用元素的索引:

ary.enum_for(:uniq).with_index { |obj, i| obj.eql?('removeme') || i }
#=> ["hello", "removeme", "hello", "testing"]

需要enum_for,因为没有块的uniq返回一个新数组而不是枚举数(这反过来又是链接with_index所需要的)。

2ul0zpep

2ul0zpep2#

除了第一次出现的词之外,拒绝所有的词怎么样,像这样。

def uniq_word(array, word)
  return array unless first = array.index(word)
  array.reject.with_index { |elem, index| index > first && elem == word }
end

array = ["hello", "removeme", "removeme", "hello", "testing"]

uniq_word(array, 'removeme')
#=> ["hello", "removeme", "hello", "testing"]

请参见Array#indexEnumerator#with_indexArray#reject
或者你可以迭代数组,只复制第一次出现的数组到一个新数组中:

def uniq_word(array, word)
  found = false

  [].tap do |result|
    array.each do |elem|
      if elem == word && !found
        found = true
        next
      end

      result << elem
    end
  end
end

array = ["hello", "removeme", "removeme", "hello", "testing"]

uniq_word(array, 'removeme')
#=> ["hello", "removeme", "hello", "testing"]

参见:

mlmc2os5

mlmc2os53#

这里有两种方法来计算感兴趣的数组。
假设给定的数组如下。

arr = ["hello", "removeme", "hello", "goodbye", "removeme", "testing"]
def removem(arr, to_remove)
  i = arr.index(to_remove)
  return arr if i.nil?
  a = arr.dup
  a.insert(i, a.delete(to_remove))
end
removem(arr, "removeme") #=> ["hello", "hello", "goodbye", "testing", "removeme"]
  #=> ["hello", "hello", "goodbye", "testing", "removeme"]
removem(arr, "goodbye")
  #=> ["hello", "removeme", "hello", "removeme", "testing", "goodbye"]
removem(arr, "missing")
  #=> ["hello", "removeme", "hello", "goodbye", "removeme", "testing"]

在每个示例中,arr不变。
参见Array#index、Array#insert和Array#delete

def removem(arr, to_remove)
  first_found = false
  indices_to_keep = []
  arr.each_with_index do |s,i|
    if s == to_remove
      if first_found == false
        indices_to_keep << i
        first_found = true
      end
    else
      indices_to_keep << i
    end
  end
  arr.values_at(*indices_to_keep)   
end
removem(arr, "removeme")
  #=> ["hello", "removeme", "hello", "goodbye", "testing"]
removem(arr, "goodbye")
  #=> ["hello", "removeme", "hello", "goodbye", "removeme", "testing"]
removem(arr, "missing")
  #=> ["hello", "removeme", "hello", "goodbye", "removeme", "testing"]

在每个示例中,arr不变。
参见Array#values_at。

disbfnqx

disbfnqx4#

如何通过添加新方法来扩展Array类?

class Array
  def uniq_specific!(targets)
    found = {}
    targets.each { |target| found[target] = false }

    delete_if do |item|
      if targets.include?(item)
        if found[item]
          true
        else
          found[item] = true
          false
        end
      else
        false
      end
    end
  end
end

array = ["hello", "removeme", "removeme", "hello", "world", "world", "testing"]
array.uniq_specific!(["removeme", "hello"])

array # => ["removeme", "hello", "world", "world", "testing"]

我们为Array类定义了一个新的方法uniq_specific!,它接受一个目标元素数组作为参数。它迭代数组并删除每个目标元素的所有出现,除了第一个。然后,我们用目标值[“removeme”,“hello”]在示例数组上调用这个方法,它会产生所需的输出。

相关问题