mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* array.c (rb_ary_product): Accept a block [ruby-core:29045]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27200 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
8d8ff193b6
commit
7cf6ecd9de
3 changed files with 24 additions and 9 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
Sat Apr 3 06:56:11 2010 Marc-Andre Lafortune <ruby-core@marc-andre.ca>
|
||||||
|
|
||||||
|
* array.c (rb_ary_product): Accept a block [ruby-core:29045]
|
||||||
|
|
||||||
Sat Apr 3 04:46:00 2010 Tanaka Akira <akr@fsij.org>
|
Sat Apr 3 04:46:00 2010 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
* tool/file2lastrev.rb (VCS#relative_to): path and @srcdir may have
|
* tool/file2lastrev.rb (VCS#relative_to): path and @srcdir may have
|
||||||
|
|
2
NEWS
2
NEWS
|
@ -22,7 +22,7 @@ with all sufficient information, see the ChangeLog file.
|
||||||
* Array#sort_by!
|
* Array#sort_by!
|
||||||
|
|
||||||
* extended methods:
|
* extended methods:
|
||||||
* Array#{uniq,uniq!} can take a block.
|
* Array#{uniq,uniq!,product} can take a block.
|
||||||
|
|
||||||
* Dir
|
* Dir
|
||||||
* new method:
|
* new method:
|
||||||
|
|
27
array.c
27
array.c
|
@ -4052,11 +4052,15 @@ rb_ary_combination(VALUE ary, VALUE num)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* ary.product(other_ary, ...)
|
* ary.product(other_ary, ...) -> array
|
||||||
|
* ary.product(other_ary, ...) { |p| block } -> ary
|
||||||
*
|
*
|
||||||
* Returns an array of all combinations of elements from all arrays.
|
* Returns an array of all combinations of elements from all arrays,
|
||||||
* The length of the returned array is the product of the length
|
* The length of the returned array is the product of the length
|
||||||
* of ary and the argument arrays
|
* of ary and the argument arrays.
|
||||||
|
* If given a block, <i>product</i> will yield all combinations
|
||||||
|
* and return self instead.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* [1,2,3].product([4,5]) # => [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
|
* [1,2,3].product([4,5]) # => [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
|
||||||
* [1,2].product([1,2]) # => [[1,1],[1,2],[2,1],[2,2]]
|
* [1,2].product([1,2]) # => [[1,1],[1,2],[2,1],[2,2]]
|
||||||
|
@ -4074,7 +4078,7 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary)
|
||||||
volatile VALUE t1 = tmpbuf(n, sizeof(int));
|
volatile VALUE t1 = tmpbuf(n, sizeof(int));
|
||||||
VALUE *arrays = (VALUE*)RSTRING_PTR(t0); /* The arrays we're computing the product of */
|
VALUE *arrays = (VALUE*)RSTRING_PTR(t0); /* The arrays we're computing the product of */
|
||||||
int *counters = (int*)RSTRING_PTR(t1); /* The current position in each one */
|
int *counters = (int*)RSTRING_PTR(t1); /* The current position in each one */
|
||||||
VALUE result; /* The array we'll be returning */
|
VALUE result = Qnil; /* The array we'll be returning, when no block given */
|
||||||
long i,j;
|
long i,j;
|
||||||
long resultlen = 1;
|
long resultlen = 1;
|
||||||
|
|
||||||
|
@ -4091,7 +4095,7 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary)
|
||||||
/* Compute the length of the result array; return [] if any is empty */
|
/* Compute the length of the result array; return [] if any is empty */
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
long k = RARRAY_LEN(arrays[i]), l = resultlen;
|
long k = RARRAY_LEN(arrays[i]), l = resultlen;
|
||||||
if (k == 0) return rb_ary_new2(0);
|
if (k == 0) return rb_block_given_p() ? ary : rb_ary_new2(0);
|
||||||
resultlen *= k;
|
resultlen *= k;
|
||||||
if (resultlen < k || resultlen < l || resultlen / k != l) {
|
if (resultlen < k || resultlen < l || resultlen / k != l) {
|
||||||
rb_raise(rb_eRangeError, "too big to product");
|
rb_raise(rb_eRangeError, "too big to product");
|
||||||
|
@ -4099,7 +4103,9 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, allocate and fill in an array of results */
|
/* Otherwise, allocate and fill in an array of results */
|
||||||
result = rb_ary_new2(resultlen);
|
if (!rb_block_given_p()) {
|
||||||
|
result = rb_ary_new2(resultlen);
|
||||||
|
}
|
||||||
for (i = 0; i < resultlen; i++) {
|
for (i = 0; i < resultlen; i++) {
|
||||||
int m;
|
int m;
|
||||||
/* fill in one subarray */
|
/* fill in one subarray */
|
||||||
|
@ -4109,7 +4115,12 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put it on the result array */
|
/* put it on the result array */
|
||||||
rb_ary_push(result, subarray);
|
if(NIL_P(result)) {
|
||||||
|
rb_yield(subarray);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rb_ary_push(result, subarray);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Increment the last counter. If it overflows, reset to 0
|
* Increment the last counter. If it overflows, reset to 0
|
||||||
|
@ -4126,7 +4137,7 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary)
|
||||||
tmpbuf_discard(t0);
|
tmpbuf_discard(t0);
|
||||||
tmpbuf_discard(t1);
|
tmpbuf_discard(t1);
|
||||||
|
|
||||||
return result;
|
return NIL_P(result) ? ary : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue