Ruby:针对特定领域采用独特的子阵列

时间:2011-08-24 10:41:42

标签: ruby

假设有一个字符串数组数组:

 array = [["John","Apples"],["Tim","Apples"],["Frank","Apples"],
  ["Tom","Pears"],["John","Pears"],["Frank","Oranges"],["Tim","Oranges"]]

现在游戏将以简单的方式选择任何在阵列的第二个值上唯一的记录,例如,结果可能是:

 array2 = [["Frank","Apples"],["Tom","Pears"],["Tim","Oranges"]]

有没有人知道是否有单行代码可以做到这一点?

4 个答案:

答案 0 :(得分:6)

Array#uniq可以采用块参数:

array.uniq { |e| e[1] }

例如:

>> array = [["John","Apples"], ["Tim","Apples"], ["Frank","Apples"], ["Tom","Pears"], ["John","Pears"], ["Frank","Oranges"], ["Tim","Oranges"]]
>> array.uniq { |e| e[1] }
=> [["John", "Apples"], ["Tom", "Pears"], ["Frank", "Oranges"]]

你可能会得到第一场比赛(而不是你的“可能”输出中的最后一场比赛),但我认为没有任何保证会选择哪一场比赛。

请注意,这只适用于1.9,1.8不喜欢它所以你必须在1.8中更努力地工作但不是那么难:

array.inject({ }) { |h,e| h[e[1]] = e[0]; h }.map { |k,v| [ v, k ] }

inject / map版本在1.8和1.9中的作用相同。此外,这个选择重复值的最后

答案 1 :(得分:5)

另一个应该适用于1.8和1.9的解决方案:

array.group_by(&:last).map { |k,v| v.last }
# => [["John", "Pears"], ["Frank", "Apples"], ["Tim", "Oranges"]]

答案 2 :(得分:3)

在Ruby 1.8中:

array.map{ |k,v| v }.uniq.map{ |uv| array.select{ |k,v| v == uv }.last }

Hash[*array.map{ |k,v| [v,k] }.flatten].map{ |k,v| [v,k] }

[更新:“mu太短”为Ruby 1.9提供了一个很好的答案,我给出的上述答案对Ruby 1.8有好处]

答案 3 :(得分:3)

facets gem实现了(在大量其他有用的方法中) uniq_by 方法:

module Enumerable
  def uniq_by #:yield:
    h = {}; inject([]) {|a,x| h[yield(x)] ||= a << x}
  end
end