7

我有一系列音乐曲目,在这个数组中,由于在多张专辑中发行,同一首歌曲可以多次出现。我正在尝试将它们从数组中删除,以便列表中只显示真正的唯一值。

哈希看起来像这样:

"tracks" => [
    [0] {
        "id" => 1,
        "Title" => "Intergalactic",
        "ArtistName" => "Beastie Boys"
    },
    [1] {
        "id" => 2,
        "Title" => "Intergalactic",
        "ArtistName" => "Beastie Boys"
    }
]

我需要一种基于Title密钥删除重复项的方法。无论如何要这样做?

4

3 回答 3

11

如果您使用 ActiveSupport,则可以使用 uniq_by,如下所示:

tracks.uniq_by {|track| track["title"]}

如果没有,那么您可以轻松地自己实现它。看到这个。

# File activesupport/lib/active_support/core_ext/array/uniq_by.rb, line 6
  def uniq_by
    hash, array = {}, []
    each { |i| hash[yield(i)] ||= (array << i) }
    array
  end
于 2011-10-06T18:08:11.757 回答
10

Array#uniq!1.9 中的方法需要一个块,所以如果你的 Hash 是h

h['tracks'].uniq! { |x| x['Title'] }

如果您使用的是 1.8,那么您可以使用以下方法伪造它:

h['tracks'] = h['tracks'].group_by { |x| x['Title'] }.values.map(&:first)

我假设您想就地修改它。

于 2011-10-06T18:45:29.427 回答
0

虽然其他方法是正确的,但我会在 SO 的其他地方发现一些额外的糖。

使用 Symbol 的这个扩展:

class Symbol
  def with(*args, &block)
    ->(caller, *rest) { caller.send(self, *rest, *args, &block) }
  end
end

而不是编写简单的迭代块,例如

foo_array.each{ |foo| foo.update_bar("baz") }, 你现在可以使用

foo_array.each &:update_bar.with("baz")

类似于你可能写的maybe_nil.try(:[], "key")...

foo_array.uniq{ |foo| foo["key"] }现在等同于

foo_array.uniq(&:[].with("key"))

我希望这有帮助

于 2019-07-01T18:03:21.037 回答