2

I have 2 internal tables typeв TYPE STANDARD TABLE OF string

The first table contains the data

| K1 |  K2 | K3 |

The second table contains the data

| K1 | K2 |

In ABAP, what is the fastest method to check if the second table entries are completely present in the first table? Maybe some inline function?

DATA lt_current_values TYPE stringtab.
DATA lt_previous_values TYPE stringtab.

APPEND 'K1' TO lt_previous_values.
APPEND 'K2' TO lt_previous_values.
APPEND 'K3' TO lt_previous_values.

APPEND 'K1' TO lt_current_values.
APPEND 'K2' TO lt_current_values.

DATA lv_count TYPE i.
LOOP AT lt_current_values INTO DATA(ls_cur).
  READ TABLE lt_previous_values TRANSPORTING NO FIELDS WITH KEY table_line = ls_cur.
  IF sy-subrc = 0.
    lv_count += 1.
  ENDIF.
ENDLOOP.

IF lv_count = LINES( lt_current_values ).
  " present => current_table values are already present in previous_table
ENDIF.
Suncatcher
  • 10,355
  • 10
  • 52
  • 90
dever
  • 23
  • 1
  • 4
  • Does this answer your question? [Find a difference of two datasets in ABAP?](https://stackoverflow.com/questions/54907235/find-a-difference-of-two-datasets-in-abap) – Jagger Nov 25 '20 at 15:02
  • Hi @Jagger Thanks for the reply. But in my case I am using a standard table. The FILTER keyword only work with SORTED or HASHED tables. – dever Nov 25 '20 at 15:08
  • You can always use a SORTED or HASHED one with NON UNIQUE KEY in place of standard tables. This would be the easiest and fastest way you asking for. – Jagger Nov 25 '20 at 15:38
  • @Jagger, I relay on the indexes of the table for mapping later. Excuse my ignorance on the topic but do do you think If i make both the tables SORTED, would it change the order similarly in both tables? I mean whether I can still relay on the indexes for mapping later? – dever Nov 25 '20 at 15:45
  • You could stay with your tables and temporarily assign them to the tables of the same structure but with SORTED or HASHED key. Then you could do your check and then you can come back to your STANDARD tables. If you post some of your code as a fully working minimal example, then I could prepare an example for you as an answer to this question. – Jagger Nov 25 '20 at 16:05
  • @Jagger I have updated the main query with the code now. Thanks a lot for the help. Waiting eagerly for your reply. :) – dever Nov 25 '20 at 16:39

2 Answers2

2

The solution would be to temporarily use hashed tables with FILTER.

DATA lt_current_values TYPE stringtab.
FIELD-SYMBOLS <ls_current_values> LIKE LINE OF lt_current_values.
DATA lt_previous_values TYPE stringtab.
FIELD-SYMBOLS <ls_previous_values> LIKE LINE OF lt_previous_values.
DATA lth_current_values LIKE HASHED TABLE OF <ls_current_values> WITH UNIQUE KEY table_line.
DATA lth_previous_values LIKE HASHED TABLE OF <ls_previous_values> WITH UNIQUE KEY table_line.

lt_previous_values = VALUE #( ( `K1` ) ( `K2` ) ( `K3` ) ).
lt_current_values = VALUE #( ( `K1` ) ( `K2` ) ).

lth_current_values = lt_current_values.
lth_previous_values = lt_previous_values.

DATA(lt_difference) = FILTER #( lth_current_values EXCEPT IN lth_previous_values WHERE table_line = table_line ).

IF lines( lt_difference ) = 0.
  BREAK-POINT.
  " present => current_table values are already present in previous_table
ENDIF.
Jagger
  • 10,350
  • 9
  • 51
  • 93
  • 1
    I've compared a couple of variants and this one seems to be the fastest one, esp. for large amounts of data. For example, 26 seconds to find 1,000 out of 1,000,000 random strings with STANDARD tables (dever's solution), 5 seconds with SORTED UNIQUE, and 1 second with this HASHED variant. Not a reliable benchmark of course, just some corner numbers. If you want to know for sure, validate with your own numbers, on your own sample data. – Florian Nov 27 '20 at 09:19
  • 1
    There are some small things that could be changed: Putting the strings into the hashed tables with "=" works only if they're free of duplicates. LOOPing and INSERTing would work for duplicate strings as well. The final result can be obtained a little shorter as `DATA(contains_all) = xsdbool( lt_difference IS INITIAL )`. – Florian Nov 27 '20 at 09:22
0

I would recommend 2 changes to your code:

DATA lt_current_values TYPE stringtab.
DATA lt_previous_values TYPE stringtab.

APPEND 'K1' TO lt_previous_values.
APPEND 'K2' TO lt_previous_values.
APPEND 'K3' TO lt_previous_values.

APPEND 'K1' TO lt_current_values.
APPEND 'K2' TO lt_current_values.
SORT lt_previous_values. " Sort the table to use binary search

DATA lv_count TYPE i.
LOOP AT lt_current_values INTO DATA(ls_cur).
  READ TABLE lt_previous_values TRANSPORTING NO FIELDS WITH KEY table_line = ls_cur BINARY SEARCH. " use Binary Search
  IF sy-subrc NE 0. " Check if it DOESN'T exist
    DATA(lv_not_contains_all) = abap_true. " Use a flag to check later
    EXIT. " Don't need to continue checking, this can save a lot of time
  ENDIF.
ENDLOOP.

IF lv_not_contains_all IS INITIAL.
  " present => current_table values are already present in previous_table
ENDIF.
cape_bsas
  • 638
  • 5
  • 13