Я хочу создать метод функции/пользовательского класса, который принимает 2 параметра:
1) IM_ITAB типа ЛЮБАЯ ТАБЛИЦА
2) IM_COMPONENT типа STRING
и возвращает 1 параметр:
1) EX_RANGE тип PIQ_SELOPT_T
Итак, алгоритм такой:
METHODS compose_range_from_itab
IMPORTING
IM_ITAB type ANY TABLE
IM_COMPONENT type STRING
EXPORTING
EX_RANGE type PIQ_SELOPT_T.
...
METHOD compose_range_from_itab.
DATA: lo_obj TYPE REF TO cl_abap_tabledescr,
wa_range TYPE selopt,
lt_range TYPE piq_selopt_t.
FIELD-SYMBOLS: <fs_line> TYPE ANY,
<fs_component> TYPE ANY.
lo_obj ?= cl_abap_typedescr=>describe_by_data( p_data = im_itab ).
READ TABLE lo_obj->key TRANSPORTING NO FIELDS WITH KEY name = im_component.
IF sy-subrc IS INITIAL.
IF LINES( im_itab ) GT 0.
LOOP AT im_itab ASSIGNING <fs_line>.
ASSIGN COMPONENT im_component OF STRUCTURE <fs_line> TO <fs_component>.
wa_range-sign = 'I'.
wa_range-option = 'EQ'.
wa_range-low = <fs_component>.
APPEND wa_range TO lt_range.
ENDLOOP.
SORT lt_range BY low.
DELETE ADJACENT DUPLICATES FROM lt_range COMPARING low.
ex_range[] = lt_range[].
ENDIF.
ENDIF.
ENDMETHOD.
Но я хочу улучшить метод дальше. Если импортируемая внутренняя таблица имеет, скажем, 255 столбцов, то перебор такой таблицы займет больше времени. Но мне нужен только один столбец, чтобы составить диапазон.
Итак, я хочу получить компоненты внутренней таблицы, затем выбрать только один компонент, создать новый тип строки, содержащий только этот компонент, затем создать внутреннюю таблицу с этим типом строки и скопировать.
Вот псевдокод, соответствующий тому, чего я хочу достичь:
append corresponding fields of im_itab into new_line_type_internal_table.
Как я могу «вырезать» один компонент и создать новый тип линии с помощью RTTS?
Тот же вопрос также задавали на SCN (пока нет ответа)
@Sandra, «Наличие 255 столбцов или даже 1000 столбцов не повлияет на ваш алгоритм» кажется не совсем правильным. Я предполагаю, что ASSIGN COMPONENT [...] OF STRUCTURE [...]
зависит от количества столбцов в таблице. По крайней мере, мой вариант ниже предполагает, что разница есть.
@Florian, нет никакой разницы, потому что для компонентов нет цикла, для каждой строки проверяется только один компонент.
Вы все усложняете, для этого вам не нужен RTTS.
DEFINE make_range.
ex_range = VALUE #( BASE ex_range ( sign = 'I' option = 'EQ' low = &1 ) ).
END-OF-DEFINITION.
LOOP AT im_itab ASSIGNING FIELD-SYMBOL(<fs_line>).
ASSIGN COMPONENT im_component OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_field>).
CHECK sy-subrc = 0 AND <fs_field> IS NOT INITIAL.
make_range <fs_field>.
ENDLOOP.
И да, как сказала Сандра, с RTTS вы не получите никакой производительности, как раз наоборот.
Я бы не стал делать CHECK sy-subrc
снова и снова. Достаточно сделать это один раз для всей таблицы, а не повторять для каждой строки. Компонент либо есть во всех строках, либо нет. Кроме того, убедитесь, что AND <fs_field> IS NOT INITIAL
действительно предназначено — наличие опции I EQ <space>
действительно может быть желаемым поведением.
Чтобы быть в безопасности, я полагаю, что каждый раз проверять назначение символов поля неплохо, но я согласен, что это избыточно. Добавил его для краткости кода, потому что проверка перед циклом требует больше строк кода. И я не мог согласиться с тем, что добавление нескольких пробелов в таблицу диапазонов является хорошей идеей, это может привести к раздуванию диапазона в наборах данных ставок, что не очень хорошо. OP может добавить один пробел в диапазон, если это необходимо.
На удивление этот вариант оказался быстрее:
CLASS-METHODS make_range_variant_2
IMPORTING
sample TYPE table_type
column TYPE string
RETURNING
VALUE(result) TYPE range_type.
METHOD make_range_variant_2.
TYPES:
BEGIN OF narrow_structure_type,
content TYPE char32,
END OF narrow_structure_type.
TYPES narrow_table_type TYPE STANDARD TABLE OF narrow_structure_type WITH EMPTY KEY.
DATA narrow_table TYPE narrow_table_type.
DATA(mapping) =
VALUE cl_abap_corresponding=>mapping_table_value(
( kind = cl_abap_corresponding=>mapping_component srcname = column dstname = 'CONTENT' ) ).
DATA(mover) =
cl_abap_corresponding=>create_with_value(
source = sample
destination = narrow_table
mapping = mapping ).
mover->execute(
EXPORTING
source = sample
CHANGING
destination = narrow_table ).
LOOP AT narrow_table ASSIGNING FIELD-SYMBOL(<row>).
INSERT VALUE #(
sign = 'I'
option = 'EQ'
low = <row>-content )
INTO TABLE result.
ENDLOOP.
ENDMETHOD.
CL_ABAP_CORRESPONDING
делегирует функцию ядра для перехода от структуры к структуре, что, по-видимому, быстрее, чем родной ABAP ASSIGN COMPONENT [...] OF STRUCTURE [...] TO FIELD-SYMBOL [...]
. Тогда фактический цикл кажется более быстрым, потому что он использует назначения с фиксированным именем.
Может быть, кто-нибудь сможет проверить.
вы предполагаете, что тип компонента char32?
к сожалению, cl_abap_corresponding не поддерживает table_line.
Для примера кода я просто предположил тип, да. Если тип неизвестен, это невозможно, потому что narrow_table
нельзя объявить статически.
this variant turned out to be faster
какие у вас доказательства? Вы проводили какой-то бенчмаркинг?
Вот варианты, которые я использовал: github.com/HrFlorianHoffmann/AbapSamples/blob/master/…
Я бы не пошел на Macro
.
Data:
lr_data type ref to data.
FIELD-SYMBOLS:
<lv_component> TYPE any,
<ls_data> TYPE any.
CREATE DATA lr_data LIKE LINE OF im_itab.
ASSIGN lr_data->* TO <ls_data>.
"Check whether im_component exists
ASSIGN COMPONENT im_component OF STRUCTURE <ls_data> TO <lv_component>.
CHECK sy-subrc EQ 0.
LOOP AT im_itab INTO <ls_data>.
APPEND VALUE #( sign = 'I' option = 'EQ' low = <lv_component> ) TO ex_range.
ENDLOOP.
Марко Поло?)) Но я ценю ваш код, он имеет смысл
@Suncatcher Надеюсь, ты понял, что я имел в виду. Макро не рекомендуется использовать в большинстве современных языков программирования. Конечно, вы можете это обсудить. Просто к вашему сведению.
Согласитесь, это обескураживает. Но это делает код более кратким и читабельным и допускается в примитивных однострочных (заполнение ячеек, структур и т. д.), где отладка не является критически необходимой.
Наличие 255 столбцов или даже 1000 столбцов не повлияет на ваш алгоритм, потому что вы используете
LOOP AT ... ASSIGNING
(на него повлияет только использование INTO). RTTS может улучшить производительность, но только при использовании таблицы диапазонов, но, вероятно, выигрыш будет очень низким. Итак, ваш вопрос действительно касается использования RTTS, или у вас есть проблема с производительностью или другая проблема?