‎2010 Jun 18 7:31 AM
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
endloopBy 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
‎2010 Jun 18 9:16 AM
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
‎2010 Jun 18 9:19 AM
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
‎2010 Jun 18 9:37 AM
>
> So plz tell me is thr some other way by which I can avoid nested loops
No.
‎2010 Jun 18 10:02 AM
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
‎2010 Jun 18 10:26 AM
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.
‎2010 Jun 18 10:20 AM
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
‎2010 Jun 18 10:28 AM
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.
‎2010 Jun 18 10:29 AM
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
‎2010 Jun 18 10:30 AM
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
‎2010 Jun 18 10:36 AM
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
‎2010 Jun 18 10:50 AM
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.
‎2010 Jun 18 11:20 AM
‎2010 Jun 18 12:42 PM
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
‎2010 Jun 18 11:54 AM
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 .
‎2010 Jun 18 3:50 PM
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.
‎2010 Jun 18 4:03 PM
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)
‎2010 Jun 19 8:31 AM
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
‎2010 Jun 20 9:10 PM
[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