13

据我所知,结果

["a", "A"].uniq 

["a", "A"]

我的问题是:

如何使 ["a", "A"].uniq 给我 ["a"] 或 ["A"]

4

7 回答 7

42

还有另一种方法可以做到这一点。您实际上可以将块传递给uniquniq!可用于评估每个元素。

["A", "a"].uniq { |elem| elem.downcase }  #=>  ["A"]

或者

["A", "a"].uniq { |elem| elem.upcase }  #=>  ["A"]

但是在这种情况下,所有内容都将不区分大小写,因此它将始终返回数组["A"]

于 2013-10-15T22:16:06.793 回答
18

只需先使案例一致。

例如:

["a","A"].map{|i| i.downcase}.uniq

编辑:如果按照 mikej 的建议,返回的元素必须与原始数组中的元素完全相同,那么这将为您做到这一点:

a.inject([]) { |result,h| result << h unless result.map{|i| i.downcase}.include?(h.downcase); result }

应该满足 mikej 的Edit2解决方案 :-)

downcased = [] 
a.inject([]) { |result,h| 
        unless downcased.include?(h.downcase);
            result << h
            downcased << h.downcase
        end;
        result}
于 2009-07-09T11:45:36.253 回答
7

您可以在大小写规范化(例如降级)值和实际值之间建立映射(哈希),然后仅从哈希中获取值:

["a", "b", "A", "C"]\
.inject(Hash.new){ |h,element| h[element.downcase] = element ; h }\
.values

选择给定单词的最后一次出现(不区分大小写):

["A", "b", "C"]

如果你想要第一次出现:

["a", "b", "A", "C"]\
.inject(Hash.new){ |h,element| h[element.downcase] = element  unless h[element.downcase]  ; h }\
.values
于 2009-07-09T12:30:17.423 回答
5
["a", "A"].map{|x| x.downcase}.uniq
=> ["a"]

或者

["a", "A"].map{|x| x.upcase}.uniq
=> ["A"]
于 2009-07-09T11:46:18.517 回答
4

如果您使用 ActiveSupport,则可以使用uniq_by。它不影响最终输出的大小写。

['A','a'].uniq_by(&:downcase) # => ['A']
于 2013-10-08T15:11:30.270 回答
2

更有效的方法是在哈希中使用 uniq 键,所以检查一下:

["a", "A"].inject(Hash.new){ |hash,j| hash[j.upcase] = j; hash}.values

将返回最后一个元素,在这种情况下

["A"]

而使用 ||= 作为赋值运算符:

["a", "A"].inject(Hash.new){ |hash,j| hash[j.upcase] ||= j; hash}.values

将返回第一个元素,在这种情况下

["a"]

特别是对于大数组,这应该更快,因为我们不会每次都使用include 搜索数组?

干杯...

于 2009-10-02T09:31:00.733 回答
0

更通用的解决方案(虽然不是最有效的):

class EqualityWrapper
  attr_reader :obj

  def initialize(obj, eq, hash)
    @obj = obj
    @eq = eq
    @hash = hash
  end

  def ==(other)
    @eq[@obj, other.obj]
  end

  alias :eql? :==

  def hash
    @hash[@obj]
  end
end

class Array
  def uniq_by(eq, hash = lambda{|x| 0 })
    map {|x| EqualityWrapper.new(x, eq, hash) }.
    uniq.
    map {|x| x.obj }
  end

  def uniq_ci
    eq = lambda{|x, y| x.casecmp(y) == 0 }
    hash = lambda{|x| x.downcase.hash }
    uniq_by(eq, hash)
  end
end

uniq_by方法采用一个检查相等性的 lambda 和一个返回哈希值的 lambda,并删除由这些数据定义的重复对象。

最重要的是,该uniq_ci方法使用不区分大小写的比较来删除重复的字符串。

于 2009-07-09T12:22:31.757 回答