03-26-2015 3:04 PM
I want to extract the smallest non-initial value from a set of fields from a structure, let+s say with 3 different time stamps, time1, time 2 and time3
lv_timst = nmin( val1 = ls_times-time1
val2 =ls_times-time2
val2 =ls_times-time3
).
All of them could be initial and I don´t want to get back initial values.
Is there a clever and fast way to achieve this without calling helper methods, replacing initial times in the structure before doing the nmin?
Thanks for your help!
03-26-2015 4:51 PM
What about something like
lv_timst = nmin(
val1 = cond type( when ls_times-time1 is not initial then ls_times-time1 else max_value )
val2 = cond type( when ls_times-time2 is not initial then ls_times-time2 else max_value )
... )
03-26-2015 3:18 PM
03-26-2015 3:25 PM
Good question, reading it through my quation was not really precise. In my specific case there will be one at least one field be not initial, so I didn´t thought of it yet.
So the correct question would be:
All of them could be initial, but at least one of them will not be initial. And I don´t want to get back initial as a result in case at least one of the value sis not initial.
Thanks already so far!
03-26-2015 3:34 PM
Well, I suppose you could use an NMAX function first to determine if there is a non-initial value, but I don't know if you would consider this "clever".
Rob
03-26-2015 3:46 PM
I would consider it clever , but I don´t see how this would work, I tried to use nmax to compare with an non-initial-value, but then this non-initial value is considered as min as well.
If the non-initial value is lower then an existing value it is considered instead of the real value, if it is higher then it is considered as well instead of the real value.
I tried like this:
lv_timst = nmin( val1 = nmax( val1 = ls_times-time1 val2 = lc_noninitial)
val2 = nmax( val1 = ls_times-time2 val2 = lc_noninitial)
val3 = nmax( val1 = ls_times-time3 val2 = lc_noninitial)
).
Let´s assume time2 is 20150323000000.
Now if my lc_noninitial is e.g. 190001010000 or something low, it is considered as higher than the initial value(in the namx e.g. for time1 which is initial), but lower than my time 2 and I get it back as minimum.
If lc_noninitial is higher, e.g. 99993112000000 then it replaces my relevant time 2 in the nmax expression. Wrong again .
But maybe you have something different in mind?
03-26-2015 3:50 PM
Yes - I meant doing a separate NMAX before doing the NMIN, to find the maximum value of the fields. If the result is not null, then there must be at least one not null entry.
All bets are off in the case of negative numbers though.
Rob
Message was edited by: Rob Burbank
03-26-2015 3:54 PM
ok, but assuming I have at least one not-null value based on the first nmax check, how would I now extract the lowest non-initial value then in the second step? There could still be initial values in e.g. time3 which would give me an initial value back as result of nmin, right?
03-26-2015 3:55 PM
And as those are all timestamps, no negative values ot be relevant here
03-26-2015 3:57 PM
03-26-2015 4:30 PM
03-26-2015 4:51 PM
Well, there's probably a way of doing this using field symbols or DO VARYING.
Rob
03-26-2015 4:51 PM
What about something like
lv_timst = nmin(
val1 = cond type( when ls_times-time1 is not initial then ls_times-time1 else max_value )
val2 = cond type( when ls_times-time2 is not initial then ls_times-time2 else max_value )
... )
03-27-2015 7:48 AM
Thank you Horst, works like a pro
Maybe it is worth mentioning in the ABAP docu for nmin, as initial values are always tricky for minimum calculations. Mid-term it would be cool if nmin might get an parameter like "IGNORING INITIAL VALUES" or so.
For those not too familar with the cond syntax (like myself :->): type is the data type of the data element considered in the condition, in my example e.g. a timestamp. In my eyample the data element for the time fields is e.g./TM/TIMESTAMP, then the synrtay goes like this:
lv_timst = nmin(
val1 = cond /TM/TIMESTAMP( when ls_times-time1 is not initial then ls_times-time1 else max_value )
val2 = cond /TM/TIMESTAMP( when ls_times-time2 is not initial then ls_times-time2 else max_value )
... )
Thanks again, Horst!
03-31-2015 11:20 AM
Hi,
What is max_value?
Is that a constant or some hidden ABAP command/function?
03-31-2015 11:28 AM
A constant with an appropriate value. For some numerical data types you can use attributes of CL_ABAP_MATH, but that's not possible for type p.
03-31-2015 11:45 AM
Thanks.
I thought I've missed another new built-in function/command in NW 7.4 (or earlier release)
03-31-2015 1:47 PM
Now the problem is solved by Horst, let me dream a bit...
data(lv_min) = nmin( tab = filter( tab = lt_times
cond = table_line is not initial ) )
I'll come back to this comment in five years 🙂
04-01-2015 5:20 PM
The master says
reduce #( init m = max
for x in tab where ( x is not initial )
next m = nmin( val1 = m val2 = x ) )
04-17-2015 2:20 PM
Had an interesting discussion with some colleagues and we tried to push this a bit futher:
Assuming we have a table like this:
Value 1 Value2
10 A
12 B
5 C
16 D
We would now like to extract not only 5 as the minimum value, but also the other value of the same line, in our case C. We where not successful so far, feels like it must be included in the nmin expression, but this does not really work. Addinf another condition after the min did also not bring expected results so far...
Any hints?
Bernd
04-19-2015 3:58 PM
Hello Bernd,
following the lines of Horst (or his "master in the background" )
data(min) = reduce ty_struc( init r = value ty_struc( col1 = nmax col2 = '' )
for m in itab
next r = cond ty_struc(
when r-col1 < m-col1 then r else m ) ).
The output class will then print the row with 5 and 'C'
cl_demo_output=>display( min ).
supposed we preceded the code with the usual declaratory bla-bla:
constants: nmax type i value cl_abap_math=>MAX_INT4.
types: begin of ty_struc,
col1 type i,
col2 type c,
end of ty_struc,
ty_struc_tab type table of ty_struc with empty key.
data(itab) = value ty_struc_tab(
( col1 = 10 col2 = 'A' )
( col1 = 12 col2 = 'B' )
( col1 = 5 col2 = 'C' )
( col1 = 16 col2 = 'D' ) ).
I don't know whether there is a shorter expression for it than the above REDUCE term.