-2

我正在尝试使用一种方法对 Array 类进行修补,当传递类似 时[1, 3, 4, 3, 0, 3, 1],将返回带有 的哈希{ 1 => [0, 6], 3 => [1, 3, 5] },其中键是我们匹配的数字,值是具有所有匹配项索引的数组。

这是我到目前为止的代码。我不知道为什么它会返回类似的东西{1=>[0, 2, 3, 1, 2, 0], 3=>[0, 2, 3, 1, 2, 0], 0=>[0, 2, 3, 1, 2, 0]}

class Array

  def dups

    matches = {}
    matches_index = []

    self.each do |i|
      self[(i_index + 1)..-1].each_with_index do |j, j_index|
        matches_index << j_index if self[i] == self[j]
      end
      matches[i] = matches_index
    end

    matches.keep_if { |key, value| value.length > 1 }
  end

end
4

5 回答 5

6

这是一个更短的版本:

class Array
  def dups
    each_index.group_by{|i| self[i]}.select{|k,v| v.size > 1}
  end
end
于 2013-07-21T20:07:51.033 回答
1

您的代码看起来非常复杂(而且非常必要)。函数式方法更容易:

class Array
  def dups
    grouped_indexed = each_with_index.group_by(&:first)
    Hash[grouped_indexed.map { |x, gs| [x, gs.map(&:last)] }]
  end
end

这还是太复杂了吗?嗯,是的,但那是因为核心缺少一些基本的抽象,比如map_by

require 'facets'
xs = [1, 3, 4, 3, 0, 3, 1]
xs.each_with_index.to_a.map_by { |x, i| [x, i] }
#= {1=>[0, 6], 3=>[1, 3, 5], 4=>[2], 0=>[4]}

老实说,即使是单行字也太冗长了。有了正确的抽象,我们应该能够写出这样的东西:

require 'awesome_functional_extensions'
xs = [1, 3, 4, 3, 0, 3, 1]
xs.with_index.group_by_pair
#= {1=>[0, 6], 3=>[1, 3, 5], 4=>[2], 0=>[4]}
于 2013-07-21T20:05:34.737 回答
0

要改进 Stas S 已经非常出色的解决方案:

class Array
  def dups
    (self.each_index.group_by {|i| self[i]}).keep_if{|k, v| v.size > 1}
  end
end

这会导致仅包含重复项的数组。

于 2013-07-21T20:31:05.780 回答
0
class Array

  def dups
    matches = {}
    self.each_with_index do |v, i|
      matches.has_key?(v) ? matches[v] << i  : matches[v] = [i]
    end
    matches
  end

end

x = [1, 3, 4, 3, 0, 3, 1]
puts x.dups
于 2013-07-21T20:08:55.303 回答
0

还有一个版本:

class Array
  def dups
    to_enum
    .with_index
    .group_by(&:first)
    .select{|_, a| a.length > 1}
    .each_value{|a| a.map!(&:last)}
  end
end
于 2013-07-21T20:21:06.450 回答