Skip to Content
Technical Articles
Author's profile photo Brandon Caulfield

The ABAP REDUCE Operator | A Tutorial for 2020

On one of my more recent projects I went through a code review and afterwards my team lead pulled me aside and asked me to explain something. As it turns out he was referring to my use of the REDUCE operator in one the class methods. Much to my surprise this particular operator is not as widely used as I thought and the reason doesn’t seem to be that it’s actually hard to use but rather it just “looks” difficult to begin with.

 

It’s a great way to quickly and efficiently sum up or collect strings in a way that lets you summarize large tables of information. It’s also, in my humble opinion, a very clean and tidy way to collect summarised data making the logic easy to read for other developers.

 

So in this article I really want to encourage you, if you aren’t already doing so, to give the REDUCE operator a try 🙂

 

The SAP documentation on this particular operator is really well written and so I made a short video simply following 3 examples directly from the online documentation.

 

These are the three examples I run through:

REDUCE – Reduction Operatorhttps://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-us/abenconstructor_expression_reduce.htm

Creating Values with FOR and REDUCE – https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-us/abencond_iteration_reduce_abexa.htm

Table Reductions, Summation of an Array – https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-us/abenreduce_simple_abexa.htm

 

There’s also a great blog post by Horst Keller on the subject – https://blogs.sap.com/2016/08/25/i-dont-like-reduce-i-love-it/

 

The example can be found in this GitHub Repo – https://github.com/brandoncaulfield/youtube-abap/blob/master/z_reduce_example.abap

 

If you have any questions or anything you’d like to add, please let me know in a comment and I’ll help where I can.

 

Thanks for reading!

Assigned Tags

      6 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Jakob Marius Kjær
      Jakob Marius Kjær

      Great stuff Brendan, thanks for this.

      I've been a "casual undercover" abap developer for about 10 years, but only recently starting to get into the more functional programming in abap. So it's to get these types of examples.

      Keep going!

      Author's profile photo Brandon Caulfield
      Brandon Caulfield
      Blog Post Author

      Thanks Jakob Marius Kjær! Im glad it was of some help. I’m busy with an Advanced ABAP Series on YouTube so if you have any concepts you’d like me to add just let me know!

      Author's profile photo Matthew Billingham
      Matthew Billingham

      I loved REDUCE so much that when I was working on a 7.31 system, I implemented it using classes/interfaces.

      Author's profile photo Brandon Caulfield
      Brandon Caulfield
      Blog Post Author

      That’s brilliant Matthew Billingham ! How did you manage that? Might be nice for anyone reading still on 7.31 or below 🙂

      Author's profile photo Matthew Billingham
      Matthew Billingham

      I'll see if I can dig it out...

      Author's profile photo Matthew Billingham
      Matthew Billingham

      It's a limited reduce, but it suited the functionality I needed at the time! So I have an interface ZIF_CONVERTOR

      interface ZIF_CONVERTER
        public .
      
      
        methods CONVERT
          importing
            !I_INPUT type ANY
          exporting
            value(E_OUTPUT) type CSEQUENCE .
      endinterface.

      And I have a static method in a utility class

      METHODS:
        reduce_table
          IMPORTING
            i_input TYPE ANY TABLE	
            i_delimiter TYPE CHAR1 DEFAULT ','
            i_convertor TYPE REF TO zif_converter OPTIONAL	
          RETURNING
            VALUE( R_REDUCED ) TYPE string.	
      ...
        METHOD reduce_table.
          DATA line_ref TYPE REF TO data.
          CREATE DATA line_ref LIKE LINE OF i_input.
          FIELD-SYMBOLS <line> TYPE any.
          ASSIGN line_ref->* TO <line>.
      
          DATA text TYPE string.
          LOOP AT i_input INTO <line>.
            IF i_converter IS NOT BOUND.
              text = <line>.
            ELSE.
              i_converter->convert( EXPORTING i_input = <line> IMPORTING e_output = text ).
            ENDIF.
            AT FIRST.
              r_reduced = text.
              CONTINUE.
            ENDAT.
            r_reduced = r_reduced && i_delimiter && text.
          ENDLOOP.
        ENDMETHOD.

      And you use it like this:

      REPORT zreduce_demo.
      
      CLASS lcl_make_upper DEFINITION.
        PUBLIC SECTION.
          INTERFACES zif_converter.
      ENDCLASS.
      
      CLASS lcl_make_upper IMPLEMENTATION.
        METHOD zif_converter~convert.
          e_output = to_upper( i_input ).
        ENDMETHOD.
      ENDCLASS.
      
      CLASS lcl_extract_numbers DEFINITION.
        PUBLIC SECTION.
          INTERFACES zif_converter.
      ENDCLASS.
      
      CLASS lcl_extract_numbers IMPLEMENTATION.
        METHOD zif_converter~convert.
          DATA input TYPE string.
          input = i_input.
          DO strlen( input ) TIMES.
            DATA pos TYPE syindex.
            pos = sy-index - 1.
            DATA char TYPE c LENGTH 1.
            char = substring( val = input off = pos len = 1 ).
            CHECK char CA '0123456789'.
            e_output = e_output && char.
          ENDDO.
        ENDMETHOD.
      ENDCLASS.
      
      START-OF-SELECTION.
        " Set up test data
        DATA test_data TYPE string_table.
        INSERT `String1` INTO TABLE test_data.
        INSERT `String2` INTO TABLE test_data.
        INSERT `String3` INTO TABLE test_data.
        " Instantiate the class that converts to upper case
        DATA to_upper_converter TYPE REF TO zif_converter.
        CREATE OBJECT to_upper_converter TYPE lcl_make_upper.
        " Instantiate the class that extracts numbers
        DATA get_number_converter TYPE REF TO zif_converter.
        CREATE OBJECT get_number_converter TYPE lcl_extract_numbers.
        " Output test data
        cl_demo_output=>begin_section( 'Test Data' ).
        cl_demo_output=>write_data( test_data ).
        cl_demo_output=>end_section( ).
        " Convert to upper case and reduce
        data uppered type string.
        uppered = zcl_utils=>reduce_table( i_input = test_data i_converter = to_upper_converter ).
        cl_demo_output=>begin_section( 'Converted to uppercase and reduced' ).
        cl_demo_output=>write_data( uppered ).
        cl_demo_output=>end_section( ).
        " Extract numbers and reduce
        data extracted type string.
        extracted = zcl_utils=>reduce_table( i_input = test_data i_converter = get_number_converter ).
        cl_demo_output=>begin_section( 'Numbers extracted and reduced' ).
        cl_demo_output=>write_data( extracted ).
        cl_demo_output=>end_section( ).
        " Display
        cl_demo_output=>display( ).