If the values are longer than a digit, or not contiguous:
data SAMPLE;
A=11; B=11; C=11; D= 3; output;
A= 1; B=22; C= 4; D=22; output;
A= 1; B= 2; C= 3; D= 4; output;
run;
data WANT;
set SAMPLE;
call sort (of A--D);
_STR = catx('|', of A--D, .);
_VALUE = prxchange('s/.*((\d+)\|)\1.*/\2/',1, _STR);
set SAMPLE;
if _VALUE ne _STR then do;
MATCH = catx(',', ifc(put(A,8. -l)=_VALUE, 'A', '')
, ifc(put(B,8. -l)=_VALUE, 'B', '')
, ifc(put(C,8. -l)=_VALUE, 'C', '')
, ifc(put(D,8. -l)=_VALUE, 'D', '')
);
end;
drop _: ;
run;
A
B
C
D
MATCH
11
11
11
3
A,B,C
1
22
4
22
B,D
1
2
3
4
The regular expression
.*((\d+)\|)\1.*/\2/
means:
/ start match pattern
.* any character(s), then
( start a group, then
(\d+) another ,group with one digit or more, then
\| a pipe character, then
) close group, then
/1 repeat the group just matched (so we want the same value twice), then
.* any character(s)
/ end match pattern, start replace pattern
\1 replace matched characters with 2nd (inner) group: (\d+)
/ end of replace pattern
You can shorten to something more compact if you want:
data WANT;
set SAMPLE;
call sort (of A--D);
_VALUE = prxchange('s/.*((\d+)\|)\1.*/\2/',1, catx('|', of A--D, .));
set SAMPLE;
MATCH = catx(',', ifc(put(A, 8. -l)=_VALUE, 'A', '')
, ifc(put(B, 8. -l)=_VALUE, 'B', '')
, ifc(put(C, 8. -l)=_VALUE, 'C', '')
, ifc(put(D, 8. -l)=_VALUE, 'D', '')
);
drop _: ;
run;
or
data WANT;
set SAMPLE;
call sort(of A--D);
_VALUE = input(prxchange('s/.*((\d+)\|)\1.*/\2/', 1, catx('|', of A--D, .)), ?? 8.);
set SAMPLE;
MATCH = catx(',', ifc(A=_VALUE, 'A', '')
, ifc(B=_VALUE, 'B', '')
, ifc(C=_VALUE, 'C', '')
, ifc(D=_VALUE, 'D', '')
);
drop _: ;
run;
... View more