Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Avoid nested loops

Karan_Chopra_
Active Participant
0 Likes
2,559

I have an internal table (itab) with a field having vale in the form as shown below;

0001-0003;0005;0007-0009 (In one row)

This means it has values 0001 to 0003 0005 0007 to 0009

I have to compare these values with some other table itab3 which has these values singly means 0001 0002 0003...etc (all in different rows ). so for that I have used nested loops because i need to expand all values to compare with itab3 table something like this :

loop at itab
    split <itab-field1> at ';' into itab2.

  loop at itab2
     split itab2-field at '-' into var1 var2.

        while var1 le var2.
           append var1 to new table
          increment var1      
       endwhile
  endloop
endloop

By this way I get vaues in new table as :

0001

0002

0003

0005

0007

0008

0009

So plz tell me is thr some other way by which I can avoid nested loops

18 REPLIES 18
Read only

Former Member
0 Likes
1,943

Create two external loops like this

loop at itab1

split itab1-field at '-' into var1 var2.

while var1 le var2.

append var1 to new table

increment var1

endwhile

endloop

loop at itab2

split itab2-field at '-' into var1 var2.

while var1 le var2.

read new table with table key field1 = var1 transporting no fields

if sy-subrc eq 0

append var1 to new table

endif.

increment var1

endwhile

endloop

Read only

Karan_Chopra_
Active Participant
0 Likes
1,943

this is not serving the purpose

i have to use itab1 when looping thru itab 2

Edited by: Karan Chopra on Jun 18, 2010 1:51 PM

Read only

rainer_hbenthal
Active Contributor
0 Likes
1,943

>

> So plz tell me is thr some other way by which I can avoid nested loops

No.

Read only

ThomasZloch
Active Contributor
0 Likes
1,943

Why avoid nested loops? You probably heard rumours that performance will suffer. Not true if the inner table is small (like probably itab2 here) or you are using sorted tables and loop at the table key.

See our ABAP performance sub-forum for more background.

Thomas

Read only

0 Likes
1,943

Even nested loops with big tables are tolerable when hashed tables are used if possible and field symbols are used.

Dont understand why so many developpers are still using tables with header lines, but this i complete different story.

Read only

Karan_Chopra_
Active Participant
0 Likes
1,943

No there is huge data this just an example I gave

it can be 0001-0100; 0150-0500 n so on (so looping hundred of times or single row )

Now u can imagine how big it can be

Read only

0 Likes
1,943

Another way is not to build a list of valid keys but to translate your values into a range table. But this is not avoiding a nested loop. If you lack performance, you should not use tables with header lines.

Read only

0 Likes
1,943

I see, well, your inner loop does not have a WHERE condition, you want to always work through the entire table itab2, so it does not even have to be sorted, even more so if itab1 has only one entry (if I understand correctly).

Why don't you compare runtimes if in doubt, nested loop vs. some probably tedious and error prone alternative that I don't want to suggest.

Thomas

P.S. moving this to ABAP performance

Read only

Karan_Chopra_
Active Participant
0 Likes
1,943

I am not using with header line but with wa

I thing is our client is << possibly confidential information removed >> and they have data in millions and performance is the main issue which they hav to deat with

soo its prohibited frm thr side to use nested loops

Edited by: Rob Burbank on Jun 20, 2010 3:14 PM

Read only

0 Likes
1,943

Thats a silly programming guideline.

Do not use into, use field symbols and assigning whereever possible. Dont build a list of all valid values, translate your specifications into a range table. Yopu can use the logical operator in to check if a value matches the range table.

Translate single values into EQ, and ranges into BT

Read only

kesavadas_thekkillath
Active Contributor
0 Likes
1,943

Check this code

Instead of the write statement , append the values to another itab.



DATA:lv_str1 TYPE char255,
     lv_low(04) TYPE n,
     lv_high(04) TYPE n.
TYPES:BEGIN OF ty_itab,
      line TYPE char255,
      END OF ty_itab.

DATA:itab TYPE TABLE OF ty_itab,
     wa TYPE ty_itab.

wa-line = '0001-0003;0005;0007-0009'.
APPEND wa TO itab.

LOOP AT itab INTO wa.
  DO.
    IF wa-line CA ';'.
      lv_str1 = wa-line+0(sy-fdpos).
      sy-fdpos = sy-fdpos + 1.
      wa-line+0(sy-fdpos) = ' '.
      CONDENSE wa-line.
      IF lv_str1 CA '-'.
        lv_low = lv_str1+0(sy-fdpos).
        lv_high = lv_str1+sy-fdpos(*).
        WHILE NOT lv_low GT lv_high.
          WRITE lv_low.
          SKIP 1.
          ADD 1 TO lv_low.
        ENDWHILE.
      ELSE.
        WRITE lv_str1.
        SKIP 1.
      ENDIF.
    ELSE.
      IF wa-line CA '-'.
        lv_low = wa-line+0(sy-fdpos).
        lv_high = wa-line+sy-fdpos(*).
        WHILE NOT lv_low GT lv_high.
          WRITE lv_low.
          SKIP 1.
          ADD 1 TO lv_low.
        ENDWHILE.
      ELSE.
        WRITE lv_str1.
        SKIP 1.
      ENDIF.
      EXIT.
    ENDIF.
  ENDDO.
ENDLOOP.

Read only

0 Likes
1,943

And

DO.
...
ENDDO.

is not a loop?

Read only

0 Likes
1,943

But still it avoids 2 splits

Yes Rainer, you are right but still my code improves performance.I checked it .



data:start type i,
     end type i,
     res type i.

data:begin of itab1 occurs 0,
     str type char255,
     end of itab1.
data:begin of itab2 occurs 0,
     str type char255,
     end of itab2.
data:var1 type char04,
     var2 type char04.

get RUN TIME FIELD start.
itab1-str = '0001-0003;0005;0007-0009'.
append itab1.
loop at itab1.
    split itab1-str at ';' into table itab2.

  loop at itab2.
     split itab2-str at '-' into var1 var2.
        while var1 le var2.
           var1 = var1 + 1.
       endwhile.
  endloop.
endloop.
get RUN TIME FIELD end.
res = end - start.
write :'code1-', res.

skip 1.

DATA:lv_str1 TYPE char255,
     lv_low(04) TYPE n,
     lv_high(04) TYPE n.
TYPES:BEGIN OF ty_itab,
      line TYPE char255,
      END OF ty_itab.

DATA:itab TYPE TABLE OF ty_itab,
     wa TYPE ty_itab.

clear:start,end,res.

get RUN TIME FIELD start.

wa-line = '0001-0003;0005;0007-0009'.
APPEND wa TO itab.

LOOP AT itab INTO wa.
  DO.
    IF wa-line CA ';'.
      lv_str1 = wa-line+0(sy-fdpos).
      sy-fdpos = sy-fdpos + 1.
      wa-line+0(sy-fdpos) = ' '.
      CONDENSE wa-line.
      IF lv_str1 CA '-'.
        lv_low = lv_str1+0(sy-fdpos).
        lv_high = lv_str1+sy-fdpos(*).
        WHILE NOT lv_low GT lv_high.
           ADD 1 TO lv_low.
        ENDWHILE.
      ELSE.
      ENDIF.
    ELSE.
      IF wa-line CA '-'.
        lv_low = wa-line+0(sy-fdpos).
        lv_high = wa-line+sy-fdpos(*).
        WHILE NOT lv_low GT lv_high.
          ADD 1 TO lv_low.
        ENDWHILE.
      ELSE.
      ENDIF.
      EXIT.
    ENDIF.
  ENDDO.
ENDLOOP.
skip 1.
get RUN TIME FIELD end.
res = end - start.
write: 'code2-',res.

Edited by: Keshav.T on Jun 18, 2010 5:24 PM

Edited by: Keshav.T on Jun 18, 2010 5:25 PM

Read only

Former Member
0 Likes
1,943

Kiran,

the code you wrote is already optimized, there is nothing much we can improve. Declare ITAB2 as below and you can avoid one SPLIT statement inside loop

DATA: L_WA(50) TYPE C VALUE '0001-0003;0005;0007-0009'.

DATA: BEGIN OF ITAB2 OCCURS 0,

from(4) TYPE C,

DELIMITER TYPE C,

TO(4) TYPE C,

END OF ITAB2.

SPLIT L_WA AT ';' INTO TABLE ITAB2 .

Read only

Former Member
0 Likes
1,943

Use something like

DATA: result_tab1 TYPE match_result_tab.
DATA: result_tab2 TYPE match_result_tab.

FIND ALL OCCURRENCES OF REGEX '([0-9]{4})-([0-9]{4})'
     IN '0001-0003;0005;0007-0009'
     RESULTS result_tab1.

FIND ALL OCCURRENCES OF REGEX '([^-][0-9]{4}[^-])'
     IN '0001-0003;0005;0007-0009'
     RESULTS result_tab2.

If your Kernel supports regular expressions. For each line in result_tab1 you will have the index of each from/to in the submatches, and in each line of result_tab2 you will find the index of all solo numbers.

Read only

Former Member
0 Likes
1,943

You can also use only one Regex:

DATA: result_tab TYPE match_result_tab.
DATA: input TYPE string VALUE '0001-0003;0005;0007-0009'.
DATA: var1 TYPE numc4.
DATA: var2 TYPE numc4.
DATA: results TYPE STANDARD TABLE OF numc4 WITH DEFAULT KEY.

FIELD-SYMBOLS: <result> TYPE match_result.
FIELD-SYMBOLS: <submatch> TYPE submatch_result.

FIND ALL OCCURRENCES OF REGEX '([0-9]{4})-([0-9]{4})|([^-][0-9]{4}[^-])'
     IN input
     RESULTS result_tab.

LOOP AT result_tab ASSIGNING <result>.
  CLEAR: var1, var2.

  READ TABLE <result>-submatches ASSIGNING <submatch> INDEX 1.

  IF ( <submatch>-offset > -1 ).
    var1 = input+<submatch>-offset(<submatch>-length).
    READ TABLE <result>-submatches ASSIGNING <submatch> INDEX 2.
    var2 = input+<submatch>-offset(<submatch>-length).

    WHILE var1 LE var2.
      APPEND var1 TO results.
      ADD 1 TO var1.
    ENDWHILE.

  ELSE.
    READ TABLE <result>-submatches ASSIGNING <submatch> INDEX 3.
    APPEND input+<submatch>-offset(<submatch>-length) TO results.
  ENDIF.
ENDLOOP.

Each line of the result table will contain three submatches, if the index of line 1 and to is greater than -1 it's an range, if the index of line 3 is greater than -1 it's a single value.

Edited by: Carsten Grafflage on Jun 18, 2010 5:20 PM (working code added)

Read only

Former Member
0 Likes
1,943

I have to compare these values with some other table itab3 which has these values singly means 0001 0002 0003...etc (all in different rows ). so for that I have used nested loops because i need to expand all values to compare with itab3

If your only requirement is to compare the two tables to determine if they are equal or not, then it depends for example how the data is stored in the internal tables.

E.g. assuming that they are nicely sorted you would get away with looping over itab3 and comparing the values against a value or interval of a current row in itab (starting with row 1). You just need to keep track at which row in itab and at which record (i.e. value or interval) within that row you are. Once you matched a complete interval or value, move on to the next record in itab or if no further one exists, simply go to the next row.

This way you'd get away with a single iteration over itab3 and itab. Obviously this would be much better from a memory perspective (no possibly huge intermediate internal table) and you'd avoid some of the iterations you'd need with your approach.

And even if the tables are not sorted one could still think of other solutions than expanding the more compact table. In the end the real questions are what are your functional requirements, how does the data look like and what is the most efficient technical way to get a solution (and obviously efficient depends on available system resources and possibly silly requirements like nested loops, though the latter one hopefully could argue against).

Cheers, harald

Read only

Former Member
0 Likes
1,943

[code]

]loop at itab

split <itab-field1> at ';' into itab2.

loop at itab2

split itab2-field at '-' into var1 var2.

while var1 le var2.

append var1 to new table

increment var1

endwhile

endloop

endloop

[code]

Your problem is not a standard LOOP in LOOP problem which can be solved with sorted, hashed or standard tables with binary search. That LOOP in LOOP comes when you have to compare the result of this processing with itab3.

Here you should simply think about a more clever processing of your lines, there must be solution which creates a sorted

table, split step by step and process the one which have '-', do appends in the right order. I think the details are your task.

Siegfried