将ABAP内部表拆分为较小部分的最短符号

将ABAP内部表拆分为较小部分的最短符号,abap,internal-tables,Abap,Internal Tables,在ABAP中,我有一个相当大的内部表,比如31000行。将其拆分为多个固定大小的较小表(例如每个1000行)的最短和最有效的方法是什么 天真的做法是: DATA lt_next_package TYPE tt_table_type. LOOP AT it_large_table INTO DATA(ls_row). INSERT ls_row INTO TABLE lt_next_package. IF lines( lt_next_package ) >= lc_package_

在ABAP中,我有一个相当大的内部表,比如31000行。将其拆分为多个固定大小的较小表(例如每个1000行)的最短和最有效的方法是什么

天真的做法是:

DATA lt_next_package TYPE tt_table_type.
LOOP AT it_large_table INTO DATA(ls_row).
  INSERT ls_row INTO TABLE lt_next_package.
  IF lines( lt_next_package ) >= lc_package_size.
    INSERT lt_next_package INTO TABLE rt_result.
    CLEAR lt_next_package.
  ENDIF.
ENDLOOP.
IF lt_next_package IS NOT INITIAL.
  INSERT lt_next_packge INTO TABLE rt_result.
ENDIF.

这很有效,但看起来很麻烦,特别是最后一个包的“不要忘记最后一个包”部分。我相信,对于较新的ABAP网格路径和表表达式,一定有更好的方法可以做到这一点,但到目前为止还没有找到。我不确定是否有正确的方法(当然,有几种方法可以做到),但您可以尝试此方法来克服最后一个软件包问题:

WHILE it_large_table IS NOT INITIAL.
  LOOP AT it_large_table ASSIGNING FIELD-SYMBOL(<ls_line>) FROM 1 TO 1000.
    INSERT <ls_line> INTO TABLE lt_next_package.
  ENDLOOP.
  DELETE it_large_table FROM 1 TO 1000.
  INSERT lt_next_package INTO TABLE rt_table.
  CLEAR: lt_next_package.
ENDWHILE.
虽然它\u大\u表不是初始值。
将字段-SYMBOL()从1分配到1000,在it_大_表处循环。
将下一个包插入表lt\U。
结束循环。
将其从1删除到1000。
将lt\U下一个\U包插入表rt\U表。
清除:下一个包。
结束时。

根据JozsefSzikszai的回答,设计了另一个选项:

rt_result = VALUE #( FOR i = 1
                     UNTIL i > round( val = lines( it_large_table) / lc_package_size
                                      dec = 0
                                      mode = cl_abap_math=>round_up )
                     LET lv_end = i * lc_package_size
                         lv_start = lv_end - lc_package_size + 1 IN
                       ( VALUE <result-type>(
                          ( LINES OF it_large_table FROM lv_start TO lv_end ) ) ) ).
rt_结果=值#(对于i=1
直到i>round(val=行(it\u大表)/lc\u包装尺寸
十二月=0
模式=cl\U abap\U数学=>四舍五入)
设lv_端=i*lc_包装尺寸
lv_开始=lv_结束-lc_包装尺寸+1英寸
(价值)(
(从lv_开始到lv_结束的it_大型_表的行)))。

对Florian和Jozsef方法进行了某种程度的重新设计

先决条件:

TYPES:
  BEGIN OF line,
    rows TYPE string,
    slice TYPE bseg_t,
  END OF line,
  itab TYPE STANDARD TABLE OF line WITH EMPTY KEY,
  bseg_t TYPE STANDARD TABLE OF bseg WITH EMPTY KEY.
DATA: result TYPE itab.
填写大表格:

SELECT * UP TO 31000 ROWS
  INTO TABLE @DATA(lt_bseg)
  FROM bseg.
这里我们构造一个表的表,其中包含主表的切片,每个切片1000行

WHILE lt_bseg IS NOT INITIAL.
  result = VALUE itab( BASE result
                       (
                       rows  = | { sy-index * 1000 }-{ sy-index * 1000 + 1000} |
                       slice = VALUE bseg_t( FOR wa IN lt_bseg INDEX INTO i FROM i + 1 TO i + 1
                                             ( LINES OF lt_bseg from i TO i + 999 ) )
                       )
                     ).
  DELETE lt_bseg FROM 1 TO 1000.
ENDWHILE.
看起来有点像我们的要求,不是吗


这里有两种方法可以构建子表,即分页:

METHOD prepare_data.
TYPES:
  BEGIN OF line,
    name  TYPE string,
    subset TYPE salv_t_row,
  END OF line,
  itab TYPE STANDARD TABLE OF line WITH EMPTY KEY.
CONSTANTS: lc_package_size TYPE i VALUE 3.
DATA: result  TYPE itab,
      it_rows TYPE salv_t_row.

DO round( val = lines( it_rows ) / lc_package_size
          dec = 0
          mode = cl_abap_math=>round_up ) TIMES.

  DATA(lv_end) = sy-index * lc_package_size.
  DATA(lv_start) = lv_end - lc_package_size + 1.
  APPEND INITIAL LINE TO result ASSIGNING FIELD-SYMBOL(<subset>).
  <subset>-name = | Subset { sy-index } |.
  <subset>-subset = VALUE #( ( LINES OF it_rows FROM lv_start TO lv_end ) ).
ENDDO.

clear result.

result = VALUE itab( FOR i = 1
                     UNTIL i > round( val = lines( it_rows ) / lc_package_size
                                   dec = 0
                                   mode = cl_abap_math=>round_up )
                     LET k = 1 IN
                     (
                      name = | Subset { i } |
                      subset = VALUE salv_t_row(
                                               LET
                                                  end = i * lc_package_size
                                                  start = end - lc_package_size + 1
                                               IN
                                                  ( LINES OF it_rows from start to end )
                                               )
                     )
                   ).
方法准备数据。
类型:
行的开始,
名称类型字符串,
子集类型salv\u t\u行,
行尾,
带空键的行的itab类型标准表。
常数:lc_包装_尺寸类型i值3。
数据:结果类型itab,
它的行类型为salv\u t\u行。
进行四舍五入(val=行(it\U行)/lc\U包装尺寸
十二月=0
mode=cl\u abap\u math=>round\u up)时间。
数据(lv_端)=sy索引*lc_包装尺寸。
数据(lv_开始)=lv_结束-lc_包装尺寸+1。
将初始行追加到结果分配字段-SYMBOL()。
-名称=|子集{sy index}|。
-子集=值#((从lv_开始到lv_结束的行)。
恩多。
结果很清楚。
结果=值itab(对于i=1
直到i>round(val=行(it_行)/lc_包装尺寸)
十二月=0
模式=cl\U abap\U数学=>四舍五入)
设k=1英寸
(
name=|子集{i}|
子集=值salv\u t\u行(
让
end=i*lc\U包装尺寸
开始=结束-lc_包装尺寸+1
在里面
(从开始到结束的it行)
)
)
).

希望这有帮助。这里的代码已经过测试,可以正常工作。只需复制粘贴(并生成一些数据)。

我不确定这是否是一个正确的问题。我不是说它是无效的,我想知道它在某种意义上是否是正确的:我们必须找到一个“最短”的语法,还是我们必须收集最有效的语法?作为一名开发人员,我的主要目标是在效率和可读性之间找到平衡,而不是关心代码长度(虽然较长的代码驱动器会降低可读性)。这里的索引是不正确的,因为您从第1行开始,并编写了1000-2000行,尽管开头的数据是正确的。稍后,您开始从数据中丢失一些记录。不确定它来自何处,但该示例是否不能被视为正确。请随意改进,因此社区始终鼓励成员在答案中查找错误并改进。对于每个子集,您在哪里有必须执行的代码?以这种方式编写的代码是一个复杂的rt_result=it_large_table。该代码随后运行。它没有内联到该语句中。其思想是将一个“平面”行表转换为一个嵌套表。结果中的每一行都是另一个包含一个“包”的表。在数组表示法中,我想要的是:[a,b,c,d,…]>[[a,b],[c,d],…]