2013-03-16 23 views
32

Tôi đang tìm cách trích xuất n cặp khóa-giá trị ngẫu nhiên từ một băm.Có tương đương với `Array :: sample` cho băm không?

+1

Sẽ giúp ích nếu bạn hiển thị mẫu băm đầu vào và giải thích thêm một chút về những gì bạn đang cố gắng sử dụng. Lấy các cặp khóa/giá trị ngẫu nhiên từ một hàm băm hiếm khi hữu ích, ngoại trừ có thể để thử nghiệm với các đầu vào ngẫu nhiên vào một cái gì đó, từ một tập đã biết. Đó là một yêu cầu rất kỳ quặc trong kinh nghiệm của tôi và làm cho tôi nghĩ rằng điều gì đó thật đáng kinh ngạc. –

+1

tôi có nhu cầu tương tự này. tôi có một băm băm, nó cũng có thể được lưu trữ như một mảng băm. và nó có ý nghĩa để có thể lấy n mục ngẫu nhiên từ một mảng. – appleLover

Trả lời

40
Hash[original_hash.to_a.sample(n)] 

Đối với Ruby 2.1,

original_hash.to_a.sample(n).to_h 
+0

là chậm, hay một ý tưởng tồi, nếu tôi lấy dữ liệu từ một băm lớn hơn? sẽ có một cách tiếp cận thay thế để cố gắng sau đó? – appleLover

+0

@appleLover Tôi không thể nghĩ ra bất cứ điều gì tốt hơn. – sawa

+1

Tôi đã tò mò vì vậy tôi đã đánh giá nó ... trong trường hợp bất kỳ ai khác tò mò https://gist.github.com/bendyorke/924612cba7432cbf36dd – cadlac

28

Tôi không biết phương pháp như vậy. Tuy nhiên, bạn có thể làm điều gì đó như:

h[h.keys.sample] 

Nếu bạn cần lấy mẫu nhiều hơn một phần thì mã sẽ phức tạp hơn một chút.

EDIT: để có được cặp giá trị quan trọng thay vì chỉ có giá trị mà bạn có thể làm điều gì đó như:

keys_sample = h.keys.sample(n) 
keys_sample.zip(keys_sample.map{|k| h[k]) 
+0

Điều này không trả lại cặp khóa-giá trị như OP muốn, chỉ giá trị cho một khóa ngẫu nhiên. –

+1

@ theTinMan đúng. Điểm lấy. Sự thật là giải pháp của sawa là giải pháp gọn gàng nhất cho ** rằng ** vấn đề –

2

Nếu mẫu của bạn chỉ có một yếu tố , bạn có thể sử dụng điều này:

sample = h.keys.sample 
h.select { |k,v| k == sample } 

Hoặc nếu mẫu của bạn có chứa nhiều hơn một phần tử, sử dụng này:

n = 2 
sample = h.keys.sample(n) 
h.select { |k,v| sample.include?(k) } 
+0

Nếu h chỉ có một phần tử, thì hãy sử dụng '= h'. Bất cứ điều gì khác là quá mức cần thiết. –

+0

Tôi đã nói nếu ** mẫu ** chỉ có một phần tử. Ví dụ của tôi giả định một băm có nhiều hơn một cặp khóa-giá trị. Sẽ không có điểm nào trong việc lấy mẫu băm với một phần tử ... – fbonetti

+0

Tôi đang đề cập đến đoạn mã đầu tiên của bạn, không phải là mã thứ hai. –

0

Một cách để thực hiện điều này:

rank_hash = {"Listen" => 1, "Download" => 60, "Share" => 150, "Purchase" => 700 } 

rank_array = rank_hash.to_a 

Thân gọi này để có được mẫu mảng ngẫu nhiên của các cặp k/v:

rank_array[rand(0..3)] 

hoặc điều này không khó mã hóa chiều dài mảng:

rank_array[rand(0..(rank_array.length) -1)] 

Ví dụ:

["Download", 60] 
2

Đọc câu trả lời đầu xếp hạng, tôi muốn đi với nó phụ thuộc:

  1. Nếu bạn muốn lấy mẫu chỉ có một phần tử từ băm, @Ivaylo Strandjev's solution chỉ dựa vào tra cứu mã băm và Array#sample:

    hsh[hsh.keys.sample] 
    
  2. Để lấy mẫu nhiều yếu tố băm, @sawa's answer thúc đẩy Array#to_h:

    hsh.to_a.sample(n).to_h 
    

Lưu ý rằng, as @cadlac mentions, hsh.to_a.sample.to_h sẽ không hoạt động như mong đợi. Nó sẽ nâng cao

TypeError: wrong element type String at 0 (expected array) 

Array#sample trong trường hợp này trả về chỉ là mảng yếu tố, và không phải là mảng chứa các mảng phần tử.

Một cách giải quyết là giải pháp của mình, cung cấp một n = 1 như một cuộc tranh cãi:

hsh.to_a.sample(1).to_h 

PS: không tìm kiếm upvotes, chỉ thêm nó như là một lời giải thích cho những người mới đến Ruby.

+0

Tùy thuộc vào định dạng của bạn, 'hsh [hsh.keys.sample] .keys' cũng có thể là giải pháp, nếu bạn đang tìm kiếm các khóa con dưới một khóa băm cụ thể. Ví dụ: 'người dùng ['John Doe'] = user_hash' không chắc chắn có cách nào 'ruby' hơn để làm điều này không. – whodini9

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