如何避免在ABAP中对内部表进行嵌套循环?

huangapple go评论85阅读模式
英文:

How to avoid nested looping over internal tables in ABAP?

问题

你能避免在这两个内部表上使用嵌套循环吗?

DATA: t_fieldcat TYPE slis_fieldcat_alv,
      t_fcat TYPE kkblo_t_fieldcat.

LOOP AT T_FIELDCAT INTO LX_FIELDCAT.
    LOOP AT T_FCAT INTO LX_FCAT.
***如果它们具有相同的字段名,将FCAT的COL_POS传递给FIELDCAT。***
      IF LX_FIELDCAT-FIELDNAME = LX_FCAT-FIELDNAME.
        LX_FIELDCAT-COL_POS = LX_FCAT-COL_POS.
        APPEND lx_fieldcat TO t_fieldcat.
        CLEAR lx_fieldcat.
      ENDIF.
 ENDLOOP.
ENDLOOP.

我想知道是否有可能在不使用嵌套循环的情况下将内部表T_FCAT的字段COL_POS分配给内部表T_FIELDCAT的字段COL_POS

英文:

Can you avoid the nested loop on these two internal tables?

DATA: t_fieldcat TYPE slis_fieldcat_alv,
      t_fcat TYPE kkblo_t_fieldcat.

LOOP AT T_FIELDCAT INTO LX_FIELDCAT.
    LOOP AT T_FCAT INTO LX_FCAT.
***If they have the same fieldname, the col_pos from FCAT will be passed to FIELDCAT.***
      IF LX_FIELDCAT-FIELDNAME = LX_FCAT-FIELDNAME.
        LX_FIELDCAT-COL_POS = LX_FCAT-COL_POS.
        APPEND lx_fieldcat TO t_fieldcat.
        CLEAR lx_fieldcat.
      ENDIF.
 ENDLOOP.
ENDLOOP.

I want to know if it is possible to assign the field COL_POS of the internal table T_FCAT to the field COL_POS of the internal table T_FIELDCAT without the nested looping.

答案1

得分: 1

以下是翻译好的部分:

所以坏消息是,我还没有找到不使用两个循环的方法。

但好消息是,我找到了另外两种解决方案。

  1. 第一种解决方案与您的问题相似,使用了field-symbols和在循环中使用WHERE子句,这样可以删除IF条件,但功能相同。对于VALUE语法,我使用BASE从现有结构(行)复制了所有内容,并使用来自另一个表的值更改其中一个字段。
DATA: t_fieldcat TYPE TABLE OF slis_fieldcat_alv,
      t_fcat TYPE kkblo_t_fieldcat.

LOOP AT t_fieldcat ASSIGNING FIELD-SYMBOL(<ls_fieldcat>).
  LOOP AT t_fcat ASSIGNING FIELD-SYMBOL(<ls_fcat>) WHERE fieldname = <ls_fieldcat>-fieldname.
    <ls_fieldcat> = VALUE #( BASE <ls_fieldcat> ( col_pos = <ls_fcat>-col_pos ) ).
  ENDLOOP.
ENDLOOP.
  1. 第二种解决方案要短得多,但对于没有学习新语法的人来说可能更复杂,但现在是最好的时间!
DATA: t_fieldcat TYPE TABLE OF slis_fieldcat_alv,
      t_fieldcat_new TYPE TABLE OF slis_fieldcat_alv,
      t_fcat TYPE kkblo_t_fieldcat.

t_fieldcat_new = VALUE #( FOR item IN t_fieldcat
                          FOR fcat IN t_fcat 
                          WHERE ( fieldname = item-fieldname )
                     ( VALUE #( BASE item col_pos = fcat-col_pos ) ) ).

这会将记录写入新表,使用FOR循环遍历t_fieldcat中的所有记录,以及t_fcat中的所有记录。这就像使用了两个循环。VALUE BASE语法与第一个解决方案中的相同。

这种语法可能当然不适用于较旧的系统。

祝编码愉快!

英文:

So the bad news is that I have not figured out a way to do this without two loops.

But the good news is that I have found out two other solutions for this.

  1. The first one being rather similar to your question, using field-symbols and a WHERE clause in the LOOP, which removes the IF condition, but works the same.
    For the VALUE syntax, I copy everything from the existing structure(row) using BASE, and change one of the fields using the value from the other table.

     DATA:&#160;t_fieldcat&#160;TYPE&#160;TABLE&#160;OF&#160;slis_fieldcat_alv,
           t_fcat&#160;&#160;&#160;&#160; TYPE&#160;kkblo_t_fieldcat.
    
     LOOP&#160;AT&#160;t_fieldcat&#160;ASSIGNING&#160;FIELD-SYMBOL(&lt;ls_fieldcat&gt;).
     &#160; LOOP&#160;AT&#160;t_fcat&#160;ASSIGNING&#160;FIELD-SYMBOL(&lt;ls_fcat&gt;)&#160;
         WHERE&#160;fieldname&#160;=&#160;&lt;ls_fieldcat&gt;-fieldname.
    
         &lt;ls_fieldcat&gt;&#160;=&#160;VALUE&#160;#(&#160;BASE&#160;&lt;ls_fieldcat&gt;&#160;
                                (&#160;col_pos&#160;=&#160;&lt;ls_fcat&gt;-col_pos&#160;)&#160;).&#160;&#160;&#160;&#160;&#160;&#160;
    
     &#160; ENDLOOP.
     ENDLOOP.
    
  2. The second solutions is much shorter, but much more complex for someone who did not learn the new syntax, but when is the best time if not now! 如何避免在ABAP中对内部表进行嵌套循环?

     DATA: t_fieldcat     TYPE TABLE OF slis_fieldcat_alv,
           t_fieldcat_new TYPE TABLE OF slis_fieldcat_alv,
           t_fcat         TYPE kkblo_t_fieldcat.
    
     t_fieldcat_new = VALUE #( FOR item IN t_fieldcat
                               FOR fcat IN t_fcat 
                               WHERE ( fieldname = item-fieldname )
                          ( VALUE #( BASE item col_pos = fcat-col_pos ) ) ).
    

This writes the records in a new table, using the FOR loop I move across all the records in t_fieldcat, and the same with the t_fcat. This is like using two LOOPs. And the VALUE BASE syntax is the same like in the first solution.

This syntax might of course not work on the older systems.

Happy coding!

答案2

得分: 0

Use could just use the read table statement.

使用 read table 语句。

read table t_fcat into lx_fcat with key fieldname = lx_fieldcat-fieldname.
if sy-subrc = 0.
...
endif.

使用 read table 从 t_fcat 表中读取数据到 lx_fcat,使用字段名 fieldname 作为关键字。如果 sy-subrc 等于 0,则执行...

But you're not passing the field col_pos to the other fieldcatalog. You're adding a new line to it which will probably run into an endless loop. I would assign a field-symbol in the first loop and write the col_pos into it:

但是你没有将字段 col_pos 传递给其他的字段目录。你只是向它添加了一行新数据,可能会导致无限循环。我建议在第一个循环中分配一个字段符号,并将 col_pos 写入其中。

data: t_fieldcat type table of slis_fieldcat_alv,
t_fcat type kkblo_t_fieldcat,
lx_fcat type kkblo_fieldcat.
field-symbols: <lx_fieldcat> type slis_fieldcat_alv.

数据声明:t_fieldcat 类型为 slis_fieldcat_alv 表,
t_fcat 类型为 kkblo_t_fieldcat,
lx_fcat 类型为 kkblo_fieldcat。
字段符号声明:<lx_fieldcat> 类型为 slis_fieldcat_alv。

loop at t_fieldcat assigning <lx_fieldcat>.
read table t_fcat into lx_fcat with key fieldname = <lx_fieldcat>-fieldname.
if sy-subrc = 0.
If they have the same fieldname, the col_pos from FCAT will be passed to FIELDCAT.
如果它们具有相同的字段名,来自 FCAT 的 col_pos 将传递给 FIELDCAT。
<lx_fieldcat>-col_pos = lx_fcat-col_pos.
endif.
endloop.

英文:

Use could just use the read table statement.

read table t_fcat into lx_fcat with key fieldname = lx_fieldcat-fieldname.
if sy-subrc = 0.
  ...
endif.

But you're not passing the field col_pos to the other fieldcatalog. You're adding a new line to it which will probably run into an endless loop. I would assign a field-symbol in the first loop and write the col_pos into it:

data: t_fieldcat type table of slis_fieldcat_alv,
      t_fcat     type kkblo_t_fieldcat,
      lx_fcat    type kkblo_fieldcat.
field-symbols: &lt;lx_fieldcat&gt; type slis_fieldcat_alv.

loop at t_fieldcat assigning &lt;lx_fieldcat&gt;.
  read table t_fcat into lx_fcat with key fieldname = &lt;lx_fieldcat&gt;-fieldname.
  if sy-subrc = 0.
***If they have the same fieldname, the col_pos from FCAT will be passed to FIELDCAT.***
    &lt;lx_fieldcat&gt;-col_pos = lx_fcat-col_pos.
  endif.
endloop.

答案3

得分: 0

为了避免两个嵌套循环,从而将渐近复杂度从O(n2)降低到O(n),我建议定义一个散列表类型,以fieldname作为字段目录表查找的键。它们经过优化,通过主表键进行访问,并获得恒定的访问时间,无论行数多少。

我们还应该记住,散列表需要额外的内存,并且基于分布式内存管理,即数据不按顺序存储在内存中,条目的内存位置是根据唯一键的散列算法计算的。因此,我们实际上是在以内存换取速度

我们定义类型:

                            WITH UNIQUE KEY fieldname.

然后仅使用一个循环和一个散列表进行查找:

      t_fieldcat_new TYPE TABLE OF slis_fieldcat_alv,
      t_fcat         TYPE kkblo_t_fieldcat.
        ...

t_fieldcat_new = VALUE #( FOR fcat IN t_fcat
( LINES OF COND #( WHEN line_exists( t_fieldcat[ fieldname = fcat-fieldname ] ) 
  THEN VALUE #( 
    LET &lt;fs_fieldcat&gt; = t_fieldcat[ fieldname = fcat-fieldname ] IN 
    ( CORRESPONDING #( BASE ( &lt;fs_fieldcat&gt; ) fcat  ) ) ) 
) ) ).

在这种情况下,语法更加简洁,但它有效。

英文:

To avoid two nested loops and therefore reduce the asymptomatic complexity from O(n<sup>2</sup>) to O(n) I would suggest to define a hashed table type with fieldname as a key for field catalog table lookups. They are optimized for access via the primary table key and attain a constant access time, irrespective of the number of lines.

We should also keep in mind that hash table requires additional memory and are based on distributed memory management, i. e. the data is not stored in order in the memory and the memory position of an entry is calculated using the hash algorithm on the basis of a unique key. So we would actully trade memory for speed.

We define the type:

TYPES: ty_t_fieldcat_hashed TYPE HASHED TABLE OF slis_fieldcat_alv
                            WITH UNIQUE KEY fieldname.

and use afterwards only one loop and a hash table for a lookup:

DATA: t_fieldcat     TYPE ty_t_fieldcat_hashed,
      t_fieldcat_new TYPE TABLE OF slis_fieldcat_alv,
      t_fcat         TYPE kkblo_t_fieldcat.
        ...


t_fieldcat_new = VALUE #( FOR fcat IN t_fcat
( LINES OF COND #( WHEN line_exists( t_fieldcat[ fieldname = fcat-fieldname ] ) 
  THEN VALUE #( 
    LET &lt;fs_fieldcat&gt; = t_fieldcat[ fieldname = fcat-fieldname ] IN 
    ( CORRESPONDING #( BASE ( &lt;fs_fieldcat&gt; ) fcat  ) ) ) 
) ) ).

The syntax in this case is even more concise, but it works.

huangapple
  • 本文由 发表于 2023年5月22日 22:30:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76307235.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定