0

我有以下数组

a3 = [["a", "b"], ["a","c"], ["b","c"], ["b", "a"], ["c","b"]]

我想得到以下输出[["a","b"], ["a","c"], ["b","c"]]并删除["b","a"] and ["c","b"]

我有以下代码

a3.each do |ary3|
x = ary3[0]
y = ary3[1]
x = ary3[1]
y = ary3[0]
if a3.include?([x,y])
   a3 - [y,x]
   end
end
print a3

我尝试使用交换,但没有运气!

谢谢您的帮助。

4

2 回答 2

6

如果两个数组包含相同的元素并且这些元素的顺序相同,则认为它们相等:

["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"}>]
于 2013-04-21T12:52:35.760 回答
0

检查这个:#delete_if如下:

a3 = [["a", "b"], ["a","c"], ["b","c"], ["b", "a"], ["c","b"]]
p a3.delete_if{|x| [["b", "a"], ["c","b"]].include? x}
#=> [["a", "b"], ["a", "c"], ["b", "c"]]

根据您的评论和描述帖子:

a3 = [["a", "b"], ["a","c"], ["b","c"], ["b", "a"], ["c","b"],["b", "a"]]
p a3.each {|x| a3.delete(x.reverse) if a3.include? x.reverse}
#=> [["a", "b"], ["a", "c"], ["b", "c"]]

基准:

require 'benchmark'
N = 10000


Benchmark.bm(20) do | x |
  a3 = [["a", "b"], ["a","c"], ["b","c"], ["b", "a"], ["c","b"],["b", "a"]]
  x.report('Mine') do
    N.times { a3.each {|x| a3.delete(x.reverse) if a3.include? x.reverse} }
  end
  a3 = [["a", "b"], ["a","c"], ["b","c"], ["b", "a"], ["c","b"],["b", "a"]]
  x.report('padde') do
    N.times { a3.uniq!(&:sort!) }
  end

end

输出:

                           user     system      total        real

Mine                   0.172000   0.000000   0.172000 (  0.361021)
padde                  0.203000   0.000000   0.203000 (  0.460026)
于 2013-04-21T11:12:29.537 回答