Project

General

Profile

Feature #15323 » 0001-Adding-Enumerable-filter_map.patch

alfonsojimenez (Alfonso Jiménez), 11/20/2018 02:24 PM

View differences:

enum.c
451 451
}
452 452

  
453 453
static VALUE
454
filter_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
455
{
456
    i = rb_yield_values2(argc, argv);
457

  
458
    if (RTEST(i)) {
459
      rb_ary_push(ary, i);
460
    }
461

  
462
    return Qnil;
463
}
464

  
465
/*
466
 *  call-seq:
467
 *     enum.filter_map { |obj| block } -> array
468
 *     enum.filter_map                 -> an_enumerator
469
 *
470
 *  Returns a new array containing the truthy results (everything except
471
 *  +false+ or +nil+) of running the +block+ for every element in +enum+.
472
 *
473
 *  If no block is given, an Enumerator is returned instead.
474
 *
475
 *
476
 *     (1..10).filter_map { |i| i * 2 if i.even? } #=> [4, 8, 12, 16, 20]
477
 *
478
 */
479
static VALUE
480
enum_filter_map(VALUE obj)
481
{
482
    VALUE ary;
483

  
484
    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
485

  
486
    ary = rb_ary_new();
487
    rb_block_call(obj, id_each, 0, 0, filter_map_i, ary);
488

  
489
    return ary;
490
}
491

  
492

  
493
static VALUE
454 494
reject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
455 495
{
456 496
    ENUM_WANT_SVALUE();
......
4070 4110
    rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
4071 4111
    rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
4072 4112
    rb_define_method(rb_mEnumerable, "filter", enum_find_all, 0);
4113
    rb_define_method(rb_mEnumerable, "filter_map", enum_filter_map, 0);
4073 4114
    rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
4074 4115
    rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
4075 4116
    rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
spec/ruby/core/enumerable/filter_map_spec.rb
1
require_relative '../../spec_helper'
2
require_relative 'fixtures/classes'
3

  
4
ruby_version_is '2.6' do
5
  describe 'Enumerable#filter_map' do
6
    before :each do
7
      @numerous = EnumerableSpecs::Numerous.new(*(1..8).to_a)
8
    end
9

  
10
    it 'returns an empty array if there are no elements' do
11
      EnumerableSpecs::Empty.new.filter_map { true }.should == []
12
    end
13

  
14
    it 'returns an array with truthy results of passing each element to block' do
15
      @numerous.filter_map { |i| i * 2 if i.even? }.should == [4, 8, 12, 16]
16
      @numerous.filter_map { |i| i * 2 }.should == [2, 4, 6, 8, 10, 12, 14, 16]
17
      @numerous.filter_map { 0 }.should == [0, 0, 0, 0, 0, 0, 0, 0]
18
      @numerous.filter_map { false }.should == []
19
      @numerous.filter_map { nil }.should == []
20
    end
21

  
22
    it 'returns an enumerator when no block given' do
23
      @numerous.filter_map.should be_an_instance_of(Enumerator)
24
    end
25
  end
26
end
test/ruby/test_enum.rb
1130 1130
    end
1131 1131
    assert_equal [1, 2, 3, 4, 5], (1..5).sort_by{|e| klass.new e}
1132 1132
  end
1133

  
1134
  def test_filter_map
1135
    @obj = (1..8).to_a
1136
    assert_equal([4, 8, 12, 16], @obj.filter_map { |i| i * 2 if i.even? })
1137
    assert_equal([2, 4, 6, 8, 10, 12, 14, 16], @obj.filter_map { |i| i * 2 })
1138
    assert_equal([0, 0, 0, 0, 0, 0, 0, 0], @obj.filter_map { 0 })
1139
    assert_equal([], @obj.filter_map { false })
1140
    assert_equal([], @obj.filter_map { nil })
1141
    assert_instance_of(Enumerator, @obj.filter_map)
1142
  end
1133 1143
end
test/ruby/test_enumerator.rb
521 521

  
522 522
  def test_size_for_enum_created_from_enumerable
523 523
    %i[find_all reject map flat_map partition group_by sort_by min_by max_by
524
      minmax_by each_with_index reverse_each each_entry].each do |method|
524
      minmax_by each_with_index reverse_each each_entry filter_map].each do |method|
525 525
      assert_equal nil, @obj.send(method).size
526 526
      assert_equal 42, @sized.send(method).size
527 527
    end
528
-