Search code examples
loopsabapinternal-tables

LOOP itab vs VALUE FOR filtering, which is more efficient?


I am trying to write a for-loop statement for the following scenario:

I have used a select to get multiple tvarvc entries data into T_TVARVC.

LOOP AT t_tvarvc INTO DATA(s_tvarvc).
    CASE s_tvarvc-name.
      WHEN c_augru.
        s_tvarvc_range = CORRESPONDING #( s_tvarvc ).
        APPEND s_tvarvc_range TO t_augru.

      WHEN c_vkorg.
        s_tvarvc_range = CORRESPONDING #( s_tvarvc ).
        APPEND s_tvarvc_range TO t_vkorg.
    ENDCASE.
ENDLOOP. 

This is what I have come up with:

DATA(t_augru) = VALUE tt_tvarvc( FOR s_tvarvc IN t_tvarvc
                                  WHERE ( name = c_augru )
                                  ( CORRESPONDING #( s_tvarvc ) ) ).

DATA(t_vkorg) = VALUE tt_tvarvc( FOR s_tvarvc IN t_tvarvc
                                  WHERE ( name = c_vkorg )
                                  ( CORRESPONDING #( s_tvarvc ) ) ). 

My observation is that, by using LOOP AT and CASE statement combo, the number of iterations will be same as the number of entries in T_TVARVC.
But when using a FOR loop for each range table, T_TVARVC has to be traversed more times to reach the desired entry thus causing multiple iterations more than the first scenario.

Can this be written in a more efficient way?


Solution

  • I agree with your observation about doubling the iterations, and to make it faster, I think the only solution is to use only one loop, considering that the internal table is not already sorted, which limits the possible solutions a lot, and I come to this solution:

    TYPES: tt_tvarvc TYPE STANDARD TABLE OF tvarvc WITH EMPTY KEY,
           BEGIN OF ty_ranges,
             t_augru TYPE tt_tvarvc,
             t_vkorg TYPE tt_tvarvc,
           END OF ty_ranges.
    CONSTANTS: c_augru TYPE tvarvc-name VALUE 'AUGRU',
               c_vkorg TYPE tvarvc-name VALUE 'VKORG'.
    
    DATA(t_tvarvc) = VALUE tt_tvarvc( for i = 1 while i <= 100 ( name = c_augru ) 
                                                               ( name = c_vkorg ) ).
    DATA(ranges) = REDUCE ty_ranges(
                      INIT ranges2 = VALUE ty_ranges( )
                      FOR <tvarv> IN t_tvarvC
                      NEXT ranges2-t_augru = COND #( WHEN <tvarv>-name = c_augru
                                                  THEN VALUE #( BASE ranges2-t_augru ( <tvarv> ) )
                                                  ELSE ranges2-t_augru )
                           ranges2-t_vkorg = COND #( WHEN <tvarv>-name = c_vkorg
                                                  THEN VALUE #( BASE ranges2-t_vkorg ( <tvarv> ) )
                                                  ELSE ranges2-t_vkorg ) ).
    

    (you will use ranges-t_augru and ranges-t_vkorg instead of t_augru and t_vkorg in your code)

    You can immediately see that the code is much less legible than any of your two snippets.

    Moreover, there is no gain in performance compared to your classic loop.

    Back to your snippet with two FOR iterations, we can see that the goal is very clear compared to the classic loop (my opinion). It's of course slower, but probably you don't need to gain a few microseconds, and so I think it's the best solution (still my opinion).