Project

General

Profile

Feature #5584 ยป by_sorah.diff

sorah (Sorah Fukumori), 11/08/2011 11:37 PM

View differences:

array.c
3934 3934
    return ary;
3935 3935
}
3936 3936

  
3937

  
3938
/*
3939
 *  call-seq:
3940
 *     ary.sample                  -> obj
3941
 *     ary.sample(random: rng)     -> obj
3942
 *     ary.sample(n)               -> new_ary
3943
 *     ary.sample(n, random: rng)  -> new_ary
3944
 *
3945
 *  Choose a random element or +n+ random elements from the array. The elements
3946
 *  are chosen by using random and unique indices into the array in order to
3947
 *  ensure that an element doesn't repeat itself unless the array already
3948
 *  contained duplicate elements. If the array is empty the first form returns
3949
 *  <code>nil</code> and the second form returns an empty array.
3950
 *
3951
 *  If +rng+ is given, it will be used as the random number generator.
3952
 */
3953

  
3954

  
3955 3937
static VALUE
3956
rb_ary_sample(int argc, VALUE *argv, VALUE ary)
3938
ary_sample(int argc, VALUE *argv, VALUE ary, int removing)
3957 3939
{
3958 3940
    VALUE nv, result, *ptr;
3959 3941
    VALUE opts, randgen = rb_cRandom;
3942
    VALUE *ptr_result;
3960 3943
    long n, len, i, j, k, idx[10];
3961 3944
    double rnds[numberof(idx)];
3962 3945

  
......
3975 3958
	    if ((len = RARRAY_LEN(ary)) == 0) return Qnil;
3976 3959
	    i = (long)(x * len);
3977 3960
	}
3978
	return RARRAY_PTR(ary)[i];
3961
	return (removing ? rb_ary_delete_at(ary, i) : RARRAY_PTR(ary)[i]);
3979 3962
    }
3980 3963
    rb_scan_args(argc, argv, "1", &nv);
3981 3964
    n = NUM2LONG(nv);
......
3994 3977
	return rb_ary_new2(0);
3995 3978
      case 1:
3996 3979
	i = (long)(rnds[0] * len);
3997
	return rb_ary_new4(1, &ptr[i]);
3980
	return (removing ? rb_ary_new3(1, rb_ary_delete_at(ary, i)) : rb_ary_new4(1, &ptr[i]));
3998 3981
      case 2:
3999 3982
	i = (long)(rnds[0] * len);
4000 3983
	j = (long)(rnds[1] * (len-1));
4001 3984
	if (j >= i) j++;
4002
	return rb_ary_new3(2, ptr[i], ptr[j]);
3985
	result = rb_ary_new3(2, ptr[i], ptr[j]);
3986
	if (removing) {
3987
	    rb_ary_delete_at(ary, i);
3988
	    if (i < j) j--;
3989
	    rb_ary_delete_at(ary, j);
3990
	}
3991
	return result;
4003 3992
      case 3:
4004 3993
	i = (long)(rnds[0] * len);
4005 3994
	j = (long)(rnds[1] * (len-1));
......
4009 3998
	    if (j >= i) l = i, g = ++j;
4010 3999
	    if (k >= l && (++k >= g)) ++k;
4011 4000
	}
4012
	return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
4001
	result = rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
4002
	if (removing) {
4003
	    long l, g;
4004
	    if (i < k) l = i, g = k, i = g, k = l;
4005
	    if (i < j) l = i, g = j, i = g, j = l;
4006
	    rb_ary_delete_at(ary, i);
4007
	    rb_ary_delete_at(ary, j);
4008
	    rb_ary_delete_at(ary, k);
4009
	}
4010
	return result;
4013 4011
    }
4014
    if (n <= numberof(idx)) {
4015
	VALUE *ptr_result;
4012
    if (removing) {
4013
	result = rb_ary_new2(n);
4014
	ptr_result = RARRAY_PTR(result);
4015
	for (i=0; i<n; i++) {
4016
	    j = (long)(rb_random_real(randgen) * --len);
4017
	    ptr_result[i] = rb_ary_delete_at(ary, j);
4018
	}
4019
    }
4020
    else if (n <= numberof(idx)) {
4016 4021
	long sorted[numberof(idx)];
4017 4022
	sorted[0] = idx[0] = (long)(rnds[0] * len);
4018 4023
	for (i=1; i<n; i++) {
......
4031 4036
	}
4032 4037
    }
4033 4038
    else {
4034
	VALUE *ptr_result;
4035 4039
	result = rb_ary_new4(len, ptr);
4036 4040
	RBASIC(result)->klass = 0;
4037 4041
	ptr_result = RARRAY_PTR(result);
......
4049 4053
    return result;
4050 4054
}
4051 4055

  
4056
/*
4057
 *  call-seq:
4058
 *     ary.sample                  -> obj
4059
 *     ary.sample(random: rng)     -> obj
4060
 *     ary.sample(n)               -> new_ary
4061
 *     ary.sample(n, random: rng)  -> new_ary
4062
 *
4063
 *  Choose a random element or +n+ random elements from the array. The elements
4064
 *  are chosen by using random and unique indices into the array in order to
4065
 *  ensure that an element doesn't repeat itself unless the array already
4066
 *  contained duplicate elements. If the array is empty the first form returns
4067
 *  <code>nil</code> and the second form returns an empty array.
4068
 *
4069
 *  If +rng+ is given, it will be used as the random number generator.
4070
 */
4071

  
4072
static VALUE
4073
rb_ary_sample(int argc, VALUE *argv, VALUE ary)
4074
{
4075
    return ary_sample(argc, argv, ary, 0);
4076
}
4077

  
4078
/*
4079
 *  call-seq:
4080
 *     ary.sample!                 -> obj
4081
 *     ary.sample!(random: rng)    -> obj
4082
 *     ary.sample!(n)              -> new_ary
4083
 *     ary.sample!(n, random: rng) -> new_ary
4084
 *
4085
 *  Choose and remove a random element or +n+ random elements from the array.
4086
 *  The elements are chosen by using random and unique indices into the array in
4087
 *  order to ensure that an element doesn't repeat itself unless the array
4088
 *  already contained duplicate elements. If the array is empty the first form
4089
 *  returns <code>nil</code> and the second form returns an empty array.
4090
 *
4091
 *  If +rng+ is given, it will be used as the random number generator.
4092
 */
4093

  
4094
static VALUE
4095
rb_ary_sample_bang(int argc, VALUE *argv, VALUE ary)
4096
{
4097
    return ary_sample(argc, argv, ary, 1);
4098
}
4052 4099

  
4053 4100
/*
4054 4101
 *  call-seq:
......
4998 5045
    rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1);
4999 5046
    rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1);
5000 5047
    rb_define_method(rb_cArray, "sample", rb_ary_sample, -1);
5048
    rb_define_method(rb_cArray, "sample!", rb_ary_sample_bang, -1);
5001 5049
    rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
5002 5050
    rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
5003 5051
    rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);