2011-12-17 28 views
14

Làm cách nào để chọn khóa băm ngẫu nhiên? Đối với my Flash+Perl card game Tôi đang cố gắng để chọn một thẻ ngẫu nhiên từ một hash nơi các phím như sau: "6 Spades", "6 câu lạc bộ", vv như thế này:Chọn một khóa ngẫu nhiên từ mã băm

my $card; 
my $i = 0; 
for $card (keys %{$user->{HAND}}) { 
    last if rand(++$i) < 1; 
} 
delete $user->{HAND}->{$card}; 
print "random card: $card\n"; 

Tôi tự hỏi nếu đó là cách đúng hoặc nếu có là một cách tốt hơn.

+1

Không đúng chút nào. Thẻ '$' trong vòng lặp' for' là ["ẩn cục bộ với vòng lặp và lấy lại giá trị cũ của nó khi thoát khỏi vòng lặp"] (http://search.cpan.org/perldoc?perlsyn#Foreach_Loops). Tức là, '$ card' trong bản in của bạn là một biến khác với' $ card' trong vòng lặp 'for'. – mob

+0

Hơn nữa, Thực tế là bạn tạo ra một số mới mỗi vượt qua skews kết quả. – ikegami

Trả lời

16

Hơi ngắn gọn hơn:

my $random_value = $hash{(keys %hash)[rand keys %hash]}; 
+1

bạn đã truyền cảm hứng cho tôi, hãy xem '$ random_val_3' trong bài đăng của tôi. –

+0

refp đẹp! nghệ thuật của perl obfuscation !! – ennuikiller

+0

Cảm ơn bạn, tôi đã theo sau $ random_key = (khóa% hash) [rand keys% hash]; –

14

Nhận giá trị ngẫu nhiên từ% băm


  1. Store phím của %hash của bạn trong @hash_keys.
  2. tạo ra một số ngẫu nhiên giữa 0 và độ dài của @hash_keys
  3. có được sự xâm nhập ngẫu nhiên từ @hash_keys
  4. sử dụng phím mua để có được giá trị ngẫu nhiên của bạn từ %hash

Đoạn mã :

my %hash = ( 
    'stack' => 'overflow', 
    'face' => 'book', 
    'inter' => 'net' 
); 

## ALTERNATIVE 1 ## 
my @hash_keys = keys %hash; 

my $random_key = $hash_keys[rand @hash_keys]; 
my $random_value = $hash{$random_key}; 

## ALTERNATIVE 2 ## 
my $random_val_2 = (%hash)[1+2*int rand keys%hash]; # TIMTOWTDI 

## ALTERNATIVE 3 ## 
my $random_val_3 = [@_=%hash]->[1|[email protected]_];   # TIMTOWTDI 
+0

"1 |" là gì? trong dòng cuối cùng làm gì? –

+0

@AlexanderFarber, đó là HOẶC bitwise, đảm bảo rằng chúng tôi chỉ nhận được các số lẻ bên trong dấu ngoặc đơn. '1 | 2 => 3', '1 | 0 => 1', '1 | 1 => 1'. Nó sẽ luôn đặt bit ít quan trọng nhất trong một số nguyên thành 1. –

+0

@refp: Tôi thấy giá trị này luôn trả về cùng giá trị lần đầu tiên được gọi là: 'perl -Mstrict -wE' my% hash = map {$ _ => $ _} 1..100; nói ((@ _ =% băm) [1 | rand @ _]) cho 1..10; '' – Zaid

1

Dưới đây là một cách khác (chứng minh làm thế nào để chọn một yếu tố ngẫu nhiên từ một danh sách dài vô danh):

my $cards; 
my $chosen; 
while (my $card = each %{$user->{HAND}}) { 
    $chosen = $card if rand(++$cards) < 1; 
} 
+0

Oh bây giờ tôi nhận được nó: Tôi không nên có "cuối cùng" trong mã ban đầu của tôi –

+0

Phải, $ đã chọn có thể được thiết lập lại nhiều hơn một lần. – ysth

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