Java
1 //シャッフル
2 for ( int i = 1 ; i <= shuffleNum ; i ++ ) {
3
4 //乱数を作成
5 ran1 = rnd1 . nextInt ( bufnum ) ;
6 ran2 = rnd2 . nextInt ( bufnum ) ;
7
8 //配列の入れ替え(乱数1と乱数2を入れ替え)
9 buff = tor [ ran1 ] ;
10 tor [ ran1 ] = tor [ ran2 ] ;
11 tor [ ran2 ] = buff ;
12 }
この入れ替え方では何度繰り返してもまともにシャッフルできません。
Java
1 < MyData > moto = new ArrayList < MyData > ( ) ; //抽出元のデータ
2 < MyData > select = new ArrayList < MyData > ( ) ; //ランダム抽出したデータ格納先
3 for ( int i = 0 ; i < 30 ; i ++ ) {
4 int ran = rnd . nextInt ( moto . size ( ) ) ;
5 select . add ( moto . get ( ran ) ) ;
6 }
こちらはgetした要素をちゃんと削除すれば大丈夫そうですね。
ランダムで欲しい要素数が、リストの一部と言うことなので
途中までシャッフルするコードを書いてみました。
(テストは20個中10個取得。)
Java
1 import java . util . Random ;
2
3 class Shuffle {
4
5 private int list_len ; //listの長さ
6 private int [ ] list ; //シャッフル前
7
8 public Shuffle ( )
9 {
10 }
11
12 public void SetList ( int num )
13 {
14 //数字を配置
15 list = new int [ num ] ;
16 list_len = num ;
17 for ( int i = 0 ; i < num ; i ++ ) {
18 list [ i ] = i ;
19 }
20 }
21
22 public int [ ] GetShuffleList ( int snum ) { //snum:シャッフルして得たい要素数
23 int pick ;
24 int [ ] s_list ;
25 Random rnd = new Random ( ) ;
26 s_list = new int [ snum ] ;
27
28 //エラーチェック省略
29 for ( int i = 0 ; i < snum ; i ++ ) {
30 pick = rnd . nextInt ( list_len ) ;
31 s_list [ i ] = list [ pick ] ; //ランダムで要素を取得、s_list[i]に格納
32 list [ pick ] = list [ list_len - 1 ] ; //最後尾の要素を長さを減らす前に持ってくる(list[pick]はもういらないので捨てる)
33 //list[pick]を捨てたくない場合は、list[pick]とlist[list_len-1]を入れ替えば要素は消えない
34 list_len -- ; //取り出したので長さを減らす(減らしたと見なす)
35 }
36 return s_list ;
37 }
38 }
39
40 class test {
41 public static void main ( String args [ ] ) {
42 Shuffle s1 = new Shuffle ( ) ;
43
44 s1 . SetList ( 20 ) ;
45 int [ ] s_list = s1 . GetShuffleList ( 10 ) ;
46 for ( int i = 0 ; i < s_list . length ; i ++ ) {
47 System . out . println ( s_list [ i ] ) ;
48 }
49 }
50 }
1億個から30個欲しい様な場合は連想配列(疎な配列が実現できるなら何でもいいです)を使って、
初期状態空、キーに対応する要素が存在しない場合はキーと同じ要素が入っていると見なして同じように部分シャッフルをかければできそうな気がします。
#追記
HashMapを使った広範囲からのランダム取得が可能なコードを書いてみました。
重複時のリトライがないので、1000個中1000個とかでもたぶん安定した性能になると思います。
Java
1 import java . util . Random ;
2 import java . util . HashMap ;
3
4 class Shuffle {
5
6 private int list_len ;
7 private HashMap < Integer , Integer > list ;
8
9 public Shuffle ( )
10 {
11 }
12
13 public void SetList ( int num )
14 {
15 list = new HashMap < Integer , Integer > ( ) ;
16 list_len = num ;
17 }
18
19 public int [ ] GetShuffleList ( int snum ) {
20 int pick ;
21 int [ ] s_list ;
22 Random rnd = new Random ( ) ;
23 s_list = new int [ snum ] ;
24
25 for ( int i = 0 ; i < snum ; i ++ ) {
26 pick = rnd . nextInt ( list_len ) ;
27 s_list [ i ] = list . containsKey ( pick ) ? list . get ( pick ) : pick ; //ランダムで要素を取得
28 list_len -- ; //取り出したので長さを減らす
29 list . put ( pick , list . containsKey ( list_len ) ? list . get ( list_len ) : list_len ) ; //最後尾の要素を持ってくる(list[pick]はもういらない)
30 }
31 return s_list ;
32 }
33 }
34
35 class test02 {
36 public static void main ( String args [ ] ) {
37 Shuffle s1 = new Shuffle ( ) ;
38
39 s1 . SetList ( 20 ) ;
40 int [ ] s_list = s1 . GetShuffleList ( 10 ) ;
41 System . out . println ( "20 => 10" ) ;
42 for ( int i = 0 ; i < s_list . length ; i ++ ) {
43 System . out . println ( s_list [ i ] ) ;
44 }
45
46 s1 . SetList ( 100000000 ) ;
47 s_list = s1 . GetShuffleList ( 10 ) ;
48 System . out . println ( "100000000 => 10" ) ;
49 for ( int i = 0 ; i < s_list . length ; i ++ ) {
50 System . out . println ( s_list [ i ] ) ;
51 }
52 }
53 }