зеркало из https://github.com/github/ruby.git
* enum.c (enum_zip): honor length of the receiver, not the
shortest length. [ruby-core:14738] * enum.c (enum_zip): returns array not enumerator for no block form. [ruby-core:14738] * enumerator.c (next_ii): do not ignore multiple values yielded. * array.c (rb_ary_zip): faster version without creating generators. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14952 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
1309c10332
Коммит
929faf7906
12
ChangeLog
12
ChangeLog
|
@ -2,6 +2,18 @@ Tue Jan 8 18:05:35 2008 Eric Hodel <drbrain@segment7.net>
|
|||
|
||||
* bin/ri, lib/rdoc/ri/*: Replace with Ryan Davis' cached ri.
|
||||
|
||||
Tue Jan 8 17:32:07 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* enum.c (enum_zip): honor length of the receiver, not the
|
||||
shortest length. [ruby-core:14738]
|
||||
|
||||
* enum.c (enum_zip): returns array not enumerator for no block
|
||||
form. [ruby-core:14738]
|
||||
|
||||
* enumerator.c (next_ii): do not ignore multiple values yielded.
|
||||
|
||||
* array.c (rb_ary_zip): faster version without creating generators.
|
||||
|
||||
Tue Jan 8 15:47:43 2008 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* enc/utf{16,32}_{be,le}.c: use &OnigEncodingName(*) instead of
|
||||
|
|
79
array.c
79
array.c
|
@ -1983,6 +1983,84 @@ rb_ary_delete_if(VALUE ary)
|
|||
return ary;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
take_i(VALUE val, VALUE *args, int argc, VALUE *argv)
|
||||
{
|
||||
if (args[1]-- == 0) rb_iter_break();
|
||||
if (argc > 1) val = rb_ary_new4(argc, argv);
|
||||
rb_ary_push(args[0], val);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
take_items(VALUE obj, long n)
|
||||
{
|
||||
VALUE result = rb_ary_new2(n);
|
||||
VALUE args[2];
|
||||
|
||||
args[0] = result; args[1] = (VALUE)n;
|
||||
rb_block_call(obj, rb_intern("each"), 0, 0, take_i, (VALUE)args);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* array.zip(arg, ...) -> an_array
|
||||
* array.zip(arg, ...) {| arr | block } -> nil
|
||||
*
|
||||
* Converts any arguments to arrays, then merges elements of
|
||||
* <i>self</i> with corresponding elements from each argument. This
|
||||
* generates a sequence of <code>self.size</code> <em>n</em>-element
|
||||
* arrays, where <em>n</em> is one more that the count of arguments. If
|
||||
* the size of any argument is less than <code>enumObj.size</code>,
|
||||
* <code>nil</code> values are supplied. If a block given, it is
|
||||
* invoked for each output array, otherwise an array of arrays is
|
||||
* returned.
|
||||
*
|
||||
* a = [ 4, 5, 6 ]
|
||||
* b = [ 7, 8, 9 ]
|
||||
*
|
||||
* [1,2,3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
|
||||
* [1,2].zip(a,b) #=> [[1, 4, 7], [2, 5, 8]]
|
||||
* a.zip([1,2],[8]) #=> [[4,1,8], [5,2,nil], [6,nil,nil]]
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_ary_zip(argc, argv, ary)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE ary;
|
||||
{
|
||||
int i, j;
|
||||
long len;
|
||||
VALUE result = Qnil;
|
||||
|
||||
len = RARRAY_LEN(ary);
|
||||
for (i=0; i<argc; i++) {
|
||||
argv[i] = take_items(argv[i], len);
|
||||
}
|
||||
if (!rb_block_given_p()) {
|
||||
result = rb_ary_new2(len);
|
||||
}
|
||||
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
VALUE tmp = rb_ary_new2(argc+1);
|
||||
|
||||
rb_ary_push(tmp, rb_ary_elt(ary, i));
|
||||
for (j=0; j<argc; j++) {
|
||||
rb_ary_push(tmp, rb_ary_elt(argv[j], i));
|
||||
}
|
||||
if (NIL_P(result)) {
|
||||
rb_yield(tmp);
|
||||
}
|
||||
else {
|
||||
rb_ary_push(result, tmp);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* array.transpose -> an_array
|
||||
|
@ -3299,6 +3377,7 @@ Init_Array(void)
|
|||
rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
|
||||
rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
|
||||
rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
|
||||
rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
|
||||
rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
|
||||
rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
|
||||
rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
|
||||
|
|
49
enum.c
49
enum.c
|
@ -1346,6 +1346,18 @@ enum_each_with_index(int argc, VALUE *argv, VALUE obj)
|
|||
}
|
||||
|
||||
|
||||
static VALUE
|
||||
call_next(VALUE *v)
|
||||
{
|
||||
return v[0] = rb_funcall(v[1], id_next, 0, 0);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_stop(VALUE *v)
|
||||
{
|
||||
return v[0] = Qundef;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
|
||||
{
|
||||
|
@ -1357,8 +1369,20 @@ zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
|
|||
tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
|
||||
rb_ary_store(tmp, 0, enum_values_pack(argc, argv));
|
||||
for (i=0; i<RARRAY_LEN(args); i++) {
|
||||
VALUE v = rb_funcall(RARRAY_PTR(args)[i], id_next, 0, 0);
|
||||
rb_ary_push(tmp, v);
|
||||
if (NIL_P(RARRAY_PTR(args)[i])) {
|
||||
rb_ary_push(tmp, Qnil);
|
||||
}
|
||||
else {
|
||||
VALUE v[2];
|
||||
|
||||
v[1] = RARRAY_PTR(args)[i];
|
||||
rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, 0);
|
||||
if (v[0] == Qundef) {
|
||||
RARRAY_PTR(args)[i] = Qnil;
|
||||
v[0] = Qnil;
|
||||
}
|
||||
rb_ary_push(tmp, v[0]);
|
||||
}
|
||||
}
|
||||
if (NIL_P(result)) {
|
||||
rb_yield(tmp);
|
||||
|
@ -1369,12 +1393,6 @@ zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
zip_b(NODE *memo)
|
||||
{
|
||||
return rb_block_call(memo->u3.value, id_each, 0, 0, zip_i, (VALUE)memo);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* enum.zip(arg, ...) => enumerator
|
||||
|
@ -1401,16 +1419,19 @@ static VALUE
|
|||
enum_zip(int argc, VALUE *argv, VALUE obj)
|
||||
{
|
||||
int i;
|
||||
VALUE result;
|
||||
ID conv;
|
||||
NODE *memo;
|
||||
VALUE result = Qnil;
|
||||
|
||||
conv = rb_intern("to_enum");
|
||||
for (i=0; i<argc; i++) {
|
||||
argv[i] = rb_funcall(argv[i], rb_intern("to_enum"), 1, ID2SYM(id_each));
|
||||
argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
|
||||
}
|
||||
RETURN_ENUMERATOR(obj, argc, argv);
|
||||
result = rb_block_given_p() ? Qnil : rb_ary_new();
|
||||
memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), obj);
|
||||
rb_rescue2(zip_b, (VALUE)memo, 0, 0, rb_eStopIteration, (VALUE)0);
|
||||
if (!rb_block_given_p()) {
|
||||
result = rb_ary_new();
|
||||
}
|
||||
memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), 0);
|
||||
rb_block_call(obj, id_each, 0, 0, zip_i, (VALUE)memo);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -365,9 +365,9 @@ enumerator_with_index(VALUE obj)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
next_ii(VALUE i, VALUE obj)
|
||||
next_ii(VALUE i, VALUE obj, int argc, VALUE *argv)
|
||||
{
|
||||
rb_fiber_yield(1, &i);
|
||||
rb_fiber_yield(argc, argv);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче