如果两个数组包含相同的元素并且这些元素的顺序相同,则认为它们相等:
["a", "b"] == ["b", "a"]
#=> false
["a", "b"] == ["a", "b"]
#=> true
所以你需要先对内部数组进行排序,然后你可以使用Array#uniq
来确保外部数组中的每个元素只会出现一次:
arr = [["a", "b"], ["a", "c"], ["b", "c"], ["b", "a"], ["c", "b"]]
arr.map(&:sort).uniq
#=> [["a", "b"], ["a", "c"], ["b", "c"]]
但是,这将arr
保持不变:
arr
#=> [["a", "b"], ["a", "c"], ["b", "c"], ["b", "a"], ["c", "b"]]
您将需要使用 mutator 方法(带有 a !
)来编辑数组:
arr = [["a", "b"], ["a", "c"], ["b", "c"], ["b", "a"], ["c", "b"]]
arr.map!(&:sort).uniq!
arr
#=> [["a", "b"], ["a", "c"], ["b", "c"]]
编辑
作为@sawa 评论的后续行动,他担心更改内部数组的顺序可能是不可取的,我对Array#uniq
. 考虑以下数组:
arr = [["b", "a"], ["a", "c"], ["b", "c"], ["b", "a"], ["c", "b"]]
我发现Array#uniq
实际上需要一个块来指定应该如何比较元素:
arr.uniq!{|x| x.sort }
arr
#=> [["b", "a"], ["a", "c"], ["b", "c"]]
很酷的是,这也适用于Symbol#to_proc
(&:
符号),实际上看起来比我原来的答案更优雅:
arr.uniq!(&:sort)
arr
#=> [["b", "a"], ["a", "c"], ["b", "c"]]
Array#sort!
如果您希望之后对内部数组进行排序,您仍然可以使用:
arr.uniq!(&:sort!)
arr
#=> [["a", "b"], ["a", "c"], ["b", "c"]]
不过,我对此的最后观察是,顺序可能并不重要,否则两个具有不同顺序的数组将不被视为相等。这让我(再次)思考,我向自己提出了一个问题:为什么不使用 a Set
?它会像这样工作:
require 'set'
sets = [Set["a", "b"], Set["a", "c"], Set["b", "c"], Set["b", "a"], Set["c", "b"]]
sets.uniq!
sets
#=> [#<Set: {"a", "b"}>, #<Set: {"a", "c"}>, #<Set: {"b", "c"}>]
请记住, Set 不允许您多次添加相同的元素,而数组则可以:
[%w[a b b b c], %w[a b b b c], %w[a b c]].uniq(&:sort)
#=> [["a", "b", "b", "b", "c"], ["a", "b", "c"]]
[Set.new(%w[a b b b c]), Set.new(%w[a b b b c]), Set.new(%w[a b c])].uniq
#=> [#<Set: {"a", "b", "c"}>]