Theo như tôi biết, kết quả củaLàm thế nào để uniq một trường hợp mảng nhạy cảm
["a", "A"].uniq
được
["a", "A"]
Câu hỏi của tôi là:
Làm thế nào để làm cho [ "a" , "A"]. Uniq cung cấp cho tôi ["a"] hoặc ["A"]
Theo như tôi biết, kết quả củaLàm thế nào để uniq một trường hợp mảng nhạy cảm
["a", "A"].uniq
được
["a", "A"]
Câu hỏi của tôi là:
Làm thế nào để làm cho [ "a" , "A"]. Uniq cung cấp cho tôi ["a"] hoặc ["A"]
Chỉ cần làm cho trường hợp nhất quán trước.
ví dụ:
["a","A"].map{|i| i.downcase}.uniq
Edit: Nếu như mikej cho thấy, các yếu tố hoàn trả phải được chính xác giống như trong mảng ban đầu, sau đó điều này sẽ làm điều đó cho bạn:
a.inject([]) { |result,h| result << h unless result.map{|i| i.downcase}.include?(h.downcase); result }
Chỉnh sửa2 Giải pháp cần thỏa mãn mikej :-)
downcased = []
a.inject([]) { |result,h|
unless downcased.include?(h.downcase);
result << h
downcased << h.downcase
end;
result}
["a", "A"].map{|x| x.downcase}.uniq
=> ["a"]
hoặc
["a", "A"].map{|x| x.upcase}.uniq
=> ["A"]
Ack! Bị đánh vào nó! – Codebeef
Một giải pháp tổng quát hơn (mặc dù không phải là hiệu quả nhất):
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
Phương pháp uniq_by
mất một lambda để kiểm tra sự bình đẳng, và một lambda mà trả về một băm và loại bỏ các đối tượng trùng lặp như được xác định bởi các dữ liệu đó.
Thực hiện trên hết, phương pháp uniq_ci
loại bỏ các chuỗi trùng lặp bằng cách sử dụng so sánh phân biệt chữ hoa chữ thường.
bạn có thể tạo bản đồ (Hash) giữa trường hợp được chuẩn hóa (ví dụ:downcased) giá trị và giá trị thực tế và sau đó chỉ mất các giá trị từ các hash:
["a", "b", "A", "C"]\
.inject(Hash.new){ |h,element| h[element.downcase] = element ; h }\
.values
chọn xuất hiện cuối cùng của một từ nhất định (case insensitive):
["A", "b", "C"]
nếu bạn muốn xuất hiện đầu tiên :
["a", "b", "A", "C"]\
.inject(Hash.new){ |h,element| h[element.downcase] = element unless h[element.downcase] ; h }\
.values
+1 Rất thông minh. – DanSingerman
Một chút hiệu quả hơn và cách là sử dụng các phím uniq trong băm, vì vậy kiểm tra này:
["a", "A"].inject(Hash.new){ |hash,j| hash[j.upcase] = j; hash}.values
sẽ trở lại yếu tố cuối cùng, trong trường hợp này
["A"]
trong khi sử dụng || = như assign điều hành:
["a", "A"].inject(Hash.new){ |hash,j| hash[j.upcase] ||= j; hash}.values
sẽ trở lại phần tử đầu tiên, trong trường hợp này
["a"]
đặc biệt đối với các mảng lớn, điều này sẽ nhanh hơn chúng tôi không tìm kiếm mảng mỗi lần sử dụng bao gồm?
cổ vũ ...
Nếu bạn đang sử dụng ActiveSupport, bạn có thể sử dụng uniq_by. Nó không ảnh hưởng đến trường hợp của đầu ra cuối cùng.
['A','a'].uniq_by(&:downcase) # => ['A']
Có một cách khác để bạn có thể thực hiện việc này. Bạn thực sự có thể chuyển một khối đến uniq
hoặc uniq!
có thể được sử dụng để đánh giá từng phần tử.
["A", "a"].uniq { |elem| elem.downcase } #=> ["A"]
hoặc
["A", "a"].uniq { |elem| elem.upcase } #=> ["A"]
Trong trường hợp này, mặc dù tất cả mọi thứ sẽ là trường hợp nhạy cảm vì vậy nó sẽ luôn luôn trở về mảng ["A"]
Câu trả lời hay. Lưu ý rằng biến thể hơi ngắn hơn là '[" A "," a "]. Uniq (&: downcase)'. – antinome
@antinome Dễ đọc hơn nhiều. –
Điều này rõ ràng nên là câu trả lời được chấp nhận ... –
Trong khi điều này có thể làm việc cho các ví dụ đưa ra nếu danh sách là một cái gì đó như ["Hello", "HELLO"] sau đó ["Hello", "HELLO"]. Bản đồ {| i | i.downcase} .uniq sẽ trả về ["hello"] không khớp với một trong hai chuỗi trong danh sách gốc. – mikej
Giải pháp đã chỉnh sửa là tốt, ngoại trừ việc nó sẽ xây dựng danh sách downcased bằng cách sử dụng result.map {| i | i.downcase} nhiều lần (một lần cho mỗi phần tử trong danh sách ban đầu) vì vậy có thể thực hiện một lần như một câu lệnh riêng biệt và lưu trữ trong một biến tạm thời nếu danh sách lớn. – mikej
Giải pháp @Eric C đơn giản hơn rất nhiều. – depquid