Count itab rows that meet some condition?
Solution 1
Do whatever feels right to you. With ~100 rows, virtually nothing will make a huge difference in runtime. For me, stability would be more important than speed in this case.
That being said, you could try this:
LOOP AT lt_my_table TRANSPORTING NO FIELDS WHERE par1 = 'XYZ'.
ADD 1 TO l_my_counter.
ENDLOOP.
Solution 2
As from 740 SP05 you can use:
DATA(lv_lines) = REDUCE i( INIT x = 0 FOR wa IN gt_itab
WHERE( F1 = 'XYZ' ) NEXT x = x + 1 ).
for counting the number of lines in gt_itab meeting codntion f1 = 'xyz'.
Solution 3
If the entries in the internal table are irrelevant you could do something like this.
DELETE lt_table WHERE par1 <> 'XYZ'.
Then you can count the remaining relevant records by using lines( lt_table )
or DESCRIBE TABLE lt_table LINES l_number_of_lines.
Here is an example.
TYPES: BEGIN OF tt_test,
par1 TYPE c LENGTH 3,
END OF tt_test.
DATA: lt_table TYPE TABLE OF tt_test.
DATA: l_number_of_lines TYPE i.
FIELD-SYMBOLS: <fs_par1> LIKE LINE OF lt_table.
APPEND INITIAL LINE TO lt_table ASSIGNING <fs_par1>.
<fs_par1>-par1 = 'XYZ'.
APPEND INITIAL LINE TO lt_table ASSIGNING <fs_par1>.
<fs_par1>-par1 = 'ABC'.
APPEND INITIAL LINE TO lt_table ASSIGNING <fs_par1>.
<fs_par1>-par1 = 'XYY'.
APPEND INITIAL LINE TO lt_table ASSIGNING <fs_par1>.
<fs_par1>-par1 = 'XYZ'.
APPEND INITIAL LINE TO lt_table ASSIGNING <fs_par1>.
<fs_par1>-par1 = 'XYZ'.
l_number_of_lines = LINES( lt_table ).
WRITE / l_number_of_lines.
DESCRIBE TABLE lt_table LINES l_number_of_lines.
WRITE / l_number_of_lines.
DELETE lt_table WHERE par1 <> 'XYZ'.
l_number_of_lines = LINES( lt_table ).
WRITE / l_number_of_lines.
Solution 4
Variant with FOR should also work, however it requires declared table type of that table:
TYPES: tt_mara TYPE TABLE OF mara WITH EMPTY KEY.
DATA(count) = lines( VALUE tt_mara( FOR line IN lt_mara WHERE ( matnr = 'XXX' ) ( line ) ) ).
Jasper
Updated on December 27, 2020Comments
-
Jasper over 3 years
I get a internal table from a Function Module call that returns ~ 100 rows. About 40% of the rows are not relevant to me because I only need the entries with
PAR1 = "XYZ"
. On SQL tables (transparent tables), I can use aselect count(*) from tab where PAR1 = "XYZ"
to get the number of valid entries.
Looking at the documentation, all I could find was the READ Table syntax to iterate through the table. My current approach is to basically have a loop and increase if the row contains the value I want. But this seems very inefficient.
Is there a better approach for my requirement?
-
Lilienthal about 6 yearsThe only correct answer for modern programming. This can of course also be used in-line (
IF REDUCE...
) so you don't need to declare any variables. Though be careful: technically this declares bothx
andwa
, though only once meaning that you can have multipleREDUCE
expressions using the same result and work area variable names. -
Pille almost 5 yearsThank you for that great answer! Is it possible to put in multipe WHERE conditions to reduce results furthermore?
-
Cold_Class over 4 yearsThis worked for me - but only after adding a space between
WHERE
and(
-
Cold_Class over 4 years@Lilienthal could you give an example how the code would look like without declaring any variables? I don't understand how it can work.
-
Lilienthal over 4 years@Cold_Class Only if you're evaluating the result directly. Say if you want to run code X only if there are more than 5 lines you can do:
IF REDUCE #( .... ) > 5. [X]. ENDIF.
Any other approach to this problem requires declaring variables the regular way meaning they can't be used in-line. -
Cold_Class over 4 years@Lilienthal I think I gotcha - by "don't need to declare any variables" you just meant
lv_lines
in this case - right? Because I thought you found a way to also get rid ofx
andwa
-
Lilienthal over 4 years@Cold_Class Ah yes, I just meant the
lv_lines
indeed. Sadly I don't think there's a way around needing to have those "temporary variables" declared.