2010-10-28 37 views

Trả lời

1

tôi giả sử bạn muốn thay đổi băm keys mà không thay đổi các giá trị:

hash = {"nr"=>"123", "name"=>"Herrmann Hofreiter", "pferd"=>"010 000 777", "land"=>"hight land"} 
header = ["nr", "name", "hourse", "land"] 
new_hash = header.zip(hash.values).to_h 

kết quả: { "nr" => "123", " tên "=>" Herrmann Hofreiter "," hourse "=>" 010 000 777 "," đất "=>" đất cao "}

+0

Một khoảnh khắc tự quảng bá ☺️, nhưng chỉ để lại ở đây: nếu cần một chút phức tạp hơn (như chọn các khóa cụ thể cùng lúc hoặc kết hợp các loại giá trị), tôi đặt cùng một lib nhỏ: https : //github.com/smileart/hash_remapper – smileart

3

Các giải pháp chính xác sẽ phụ thuộc vào định dạng mà bạn có các phím mới trong (hoặc nếu bạn có thể lấy được chìa khóa mới từ chìa khóa cũ.)

Giả sử bạn có một băm h có phím bạn muốn thay đổi và một hash new_keys mà các bản đồ các phím hiện tại để các phím mới, bạn có thể làm:

h.keys.each do |key| 
    h[new_keys[key]] = h[key] # add entry for new key 
    k.delete(key)    # remove old key 
end 
+1

Điều này sẽ xóa giá trị cho' khóa' khi ' new_keys' vô tình xảy ra để trả về 'khóa' chính nó cho một số' khóa'. câu trả lời của barbolos cho câu hỏi này: http://stackoverflow.com/questions/4137824 khắc phục vấn đề này. – sawa

+2

thay vì điều này bạn có thể sử dụng 'h.keys.each {| key | h [new_keys [key]] = h.delete (khóa)} ' – Selvamani

+0

@Selvamani, xem câu trả lời của tôi và tạo câu trả lời từ nhận xét của bạn. –

73

Giả sử bạn có một Hash mà bản đồ phím cũ để chìa khóa mới, bạn có thể làm một cái gì đó giống như

hsh.map {|k, v| [key_map[k], v] }.to_h 
+4

Bạn là người đàn ông! Băm của bạn là hoàn toàn tuyệt vời! Cảm ơn một lần nữa cho viên ngọc này!:) – CalebHC

+1

Nó cũng giả sử bạn có 'key_map' được định nghĩa là băm của cặp khóa/giá trị trong đó khóa là khóa cũ và giá trị là khóa mới được hoán đổi. –

-1

Nếu bạn cũng lo lắng về hiệu suất, đây là nhanh hơn:

hsh.keys.each { |k| hsh[ key_map[k] ] = hsh.delete(k) if key_map[k] } 

Bạn không tạo ra một Hash mới và bạn đổi tên chỉ các phím cần thiết. Điều đó mang đến cho bạn hiệu suất tốt hơn.

Bạn có thể tìm thêm chi tiết trong "How to elegantly rename all keys in a hash in Ruby?"

+0

Điều này bị ngắt nếu' key_map [k] 'là số không . –

3

Một cách khác để làm điều đó là:

hash = { 
    'foo' => 1, 
    'bar' => 2 
} 

new_keys = { 
    'foo' => 'foozle', 
    'bar' => 'barzle' 
} 

new_keys.values.zip(hash.values_at(*new_keys.keys)).to_h 
# => {"foozle"=>1, "barzle"=>2} 

Breaking nó xuống:

new_keys 
.values # => ["foozle", "barzle"] 
.zip(
    hash.values_at(*new_keys.keys) # => [1, 2] 
) # => [["foozle", 1], ["barzle", 2]] 
.to_h 
# => {"foozle"=>1, "barzle"=>2} 

Đó là thời gian chuẩn .. .

Trong khi tôi thích sự đơn giản của câu trả lời Jörn, tôi đang không chắc nó là nhanh như nó phải được, sau đó tôi thấy bình luận selvamani của:

require 'fruity' 

HASH = { 
    'foo' => 1, 
    'bar' => 2 
} 

NEW_KEYS = { 
    'foo' => 'foozle', 
    'bar' => 'barzle' 
} 

compare do 
    mittag { HASH.dup.map {|k, v| [NEW_KEYS[k], v] }.to_h } 
    ttm  { h = HASH.dup; NEW_KEYS.values.zip(h.values_at(*NEW_KEYS.keys)).to_h } 
    selvamani { h = HASH.dup; h.keys.each { |key| h[NEW_KEYS[key]] = h.delete(key)}; h } 
end 

# >> Running each test 2048 times. Test will take about 1 second. 
# >> selvamani is faster than ttm by 39.99999999999999% ± 10.0% 
# >> ttm is faster than mittag by 10.000000000000009% ± 10.0% 

Những đang chạy tốc độ với nhau rất chặt chẽ khôn ngoan, vì vậy bất kỳ sẽ làm, nhưng 39% trả tiền theo thời gian để xem xét điều đó. Một vài câu trả lời không được đưa vào bởi vì có những sai sót tiềm ẩn nơi chúng trả về kết quả xấu.

0
h = { 'foo'=>1, 'bar'=>2 } 
key_map = { 'foo'=>'foozle', 'bar'=>'barzle' } 

h.each_with_object({}) { |(k,v),g| g[key_map[k]]=v } 
    #=> {"foozle"=>1, "barzle"=>2} 

hoặc

h.reduce({}) { |g,(k,v)| g.merge(key_map[k]=>v) } 
    #=> {"foozle"=>1, "barzle"=>2} 
+0

Tôi nghĩ rằng việc hợp nhất cuộc gọi cho mỗi phím sẽ tương đối chậm – Josh

+0

@Josh, bạn là chính xác. Tôi đã chạy lại chuẩn của @ theTinMan với hai phương thức được thêm vào và thu được các kết quả sau: "selvamani nhanh hơn ttm 19,99% ± 1,0%; ttm tương tự như caryewo (sử dụng' each_with_object'); caryewo tương tự như mittag; nhanh hơn caryred (sử dụng 'reduce') bằng 70.0% ± 10.0%". –

Các vấn đề liên quan