Đây có phải là cách tốt nhất để sắp xếp một hàm băm và trả về đối tượng Hash (thay vì Array):
h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
# => {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
Hash[h.sort]
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
Đây có phải là cách tốt nhất để sắp xếp một hàm băm và trả về đối tượng Hash (thay vì Array):
h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
# => {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
Hash[h.sort]
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
Câu trả lời:
Trong Ruby 2.1 rất đơn giản:
h.sort.to_h
h.sort{|a,z|a<=>z}.to_h
(đã kiểm tra 2.1.10, 2.3.3)
a
là một mảng, không chỉ là chìa khóa). Tôi đã xóa bình luận của tôi.
h.map(&:sort).map(&:to_h)
.
Lưu ý: Ruby> = 1.9.2 có hàm băm giữ trật tự: các khóa thứ tự được chèn sẽ là thứ tự chúng được liệt kê. Dưới đây áp dụng cho các phiên bản cũ hơn hoặc mã tương thích ngược.
Không có khái niệm về một hàm băm được sắp xếp. Vì vậy, không, những gì bạn đang làm không đúng.
Nếu bạn muốn nó được sắp xếp để hiển thị, hãy trả về một chuỗi:
"{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"
hoặc, nếu bạn muốn các phím theo thứ tự:
h.keys.sort
hoặc, nếu bạn muốn truy cập các yếu tố theo thứ tự:
h.sort.map do |key,value|
# keys will arrive in order to this block, with their associated value.
end
nhưng tóm lại, thật vô nghĩa khi nói về một hàm băm được sắp xếp. Từ các tài liệu , "Thứ tự mà bạn duyệt qua hàm băm bằng khóa hoặc giá trị có thể có vẻ tùy ý và thường sẽ không theo thứ tự chèn." Vì vậy, chèn các khóa theo thứ tự cụ thể vào hàm băm sẽ không có ích.
Tôi đã luôn luôn sử dụng sort_by
. Bạn cần phải bọc #sort_by
đầu ra Hash[]
để làm cho nó xuất ra một hàm băm, nếu không nó sẽ tạo ra một mảng các mảng. Ngoài ra, để thực hiện điều này, bạn có thể chạy #to_h
phương thức trên mảng bộ dữ liệu để chuyển đổi chúng thành k=>v
cấu trúc (hàm băm).
hsh ={"a" => 1000, "b" => 10, "c" => 200000}
Hash[hsh.sort_by{|k,v| v}] #or hsh.sort_by{|k,v| v}.to_h
Có một câu hỏi tương tự trong " Cách sắp xếp Ruby Hash theo giá trị số? ".
sort_by
trên một hàm băm sẽ trả về một mảng. Bạn sẽ cần phải vạch ra nó như là một hàm băm một lần nữa. Hash[hsh.sort_by{|k,v| v}]
hsh.sort_by(&:last).to_h => {"b"=>10, "a"=>1000, "c"=>200000}
.
to_h
chỉ được hỗ trợ trong Ruby 2.1.0+
sort_by{|k,v| v}.to_h)
Không, không phải (Ruby 1.9.x)
require 'benchmark'
h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
many = 100_000
Benchmark.bm do |b|
GC.start
b.report("hash sort") do
many.times do
Hash[h.sort]
end
end
GC.start
b.report("keys sort") do
many.times do
nh = {}
h.keys.sort.each do |k|
nh[k] = h[k]
end
end
end
end
user system total real
hash sort 0.400000 0.000000 0.400000 ( 0.405588)
keys sort 0.250000 0.010000 0.260000 ( 0.260303)
Đối với băm lớn, sự khác biệt sẽ tăng lên gấp 10 lần và hơn thế nữa
Bạn đã đưa ra câu trả lời tốt nhất cho chính mình trong OP: Hash[h.sort]
Nếu bạn khao khát có nhiều khả năng hơn, đây là sửa đổi tại chỗ của hàm băm ban đầu để sắp xếp nó:
h.keys.sort.each { |k| h[k] = h.delete k }
Sắp xếp băm theo khóa , trả về hàm băm trong Ruby
Với phá hủy và Hash # sort
hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h
Vô số # sort_by
hash.sort_by { |k, v| k }.to_h
Hash # sort với hành vi mặc định
h = { "b" => 2, "c" => 1, "a" => 3 }
h.sort # e.g. ["a", 20] <=> ["b", 30]
hash.sort.to_h #=> { "a" => 3, "b" => 2, "c" => 1 }
Lưu ý: <Ruby 2.1
array = [["key", "value"]]
hash = Hash[array]
hash #=> {"key"=>"value"}
Lưu ý:> Ruby 2.1
[["key", "value"]].to_h #=> {"key"=>"value"}
v
bạn nên thêm tiền tố vào dấu gạch dướihash.sort_by { |k, _v| k }.to_h
ActiveSupport :: OrderedHash là một tùy chọn khác nếu bạn không muốn sử dụng ruby 1.9.2 hoặc cuộn các cách giải quyết của riêng bạn.
@ordered = {}
@unordered.keys.sort.each do |key|
@ordered[key] = @unordered[key]
end
Tôi có cùng một vấn đề (tôi phải sắp xếp thiết bị của mình theo tên của họ) và tôi đã giải quyết như sau:
<% @equipments.sort.each do |name, quantity| %>
...
<% end %>
@equipments là một hàm băm mà tôi xây dựng trên mô hình của mình và trả về bộ điều khiển của tôi. Nếu bạn gọi .sort, nó sẽ sắp xếp hàm băm dựa trên giá trị khóa của nó.
Tôi thích giải pháp trong bài trước.
Tôi làm một lớp nhỏ, gọi nó class AlphabeticalHash
. Nó cũng có một phương thức được gọi ap
, chấp nhận một đối số, a Hash
, làm đầu vào : ap variable
. Akin đến trang ( pp variable
)
Nhưng nó sẽ (thử và) in trong danh sách theo thứ tự chữ cái (các phím của nó). Nếu không ai muốn sử dụng nó, nó có sẵn như một viên ngọc quý, bạn có thể cài đặt nó như sau:gem install alphabetical_hash
Đối với tôi, điều này là đủ đơn giản. Nếu người khác cần nhiều chức năng hơn, hãy cho tôi biết, tôi sẽ đưa nó vào đá quý.
EDIT: Tín dụng cho Peter , người đã cho tôi ý tưởng. :)
each
hoặceach_pair
lặp lại nó. Thậm chí sau đó, tôi có thể vẫn lấy các phím, sắp xếp chúng, sau đó lặp lại chúng để lấy các giá trị khi cần. Điều đó đảm bảo mã sẽ hoạt động chính xác trên các viên ruby cũ.