Comparing Two Lists/ Variables
Is there a way to compare the content of two variables/ lists and if they share a common element/ value return 1?
Example the two below both have "Yellow":
Set y = "Red, Green, Orange, Yellow"
Set x = "Purple, Black, Yellow, Pink"
The lists I am working with have over 30 elements/values that vary so it is difficult to hard code it to say look for "Yellow".
Product version: IRIS 2022.1
If you want to treat them as lists, you probably want to use $LISTFROMSTRING along with $LISTGET, $LISTFIND, and $LISTLENGTH. All of which can be abbreviated to their initials, by the way - $LFS, $LG, $LF, $LL.
Thank you @David Hockenbroch , I will try this out
eventually better to check for longer lists
USER>s x=$lfs("Purple,Black,Yellow,Pink") USER>s y=$lfs("Red,Green,Orange,Yellow") USER>f z="y","x" f i=1:1:$ll(@z) i $i(dif($li(@z,i))) USER>zw dif dif("Black")=1 dif("Green")=1 dif("Orange")=1 dif("Pink")=1 dif("Purple")=1 dif("Red")=1 dif("Yellow")=2
looping with $o() over dif() allows programmatic check
Thank you @Robert Cemper
This one will incorrectly flag an entry being in both lists if it appears twice in 1 list. That may not be possible due to constrants elsewhere, but it's something to be careful about
@Herman Slagman this worked. However, when I had more than one repeating values e.g.
Set y="Red,Green,Orange,Yellow,z,y,x,w,v"
It only returned that Yellow was found in both lists and ignored the Orange. I probably just need to edit the code that you shared. Thank you!
You can edit (or enhance) the above code to give you all matching elements. Below I share a code with you where you can choose the result data type (%List or %String) and the result scope (all the matching elements or just the first match).
/// Find common items of two lists or in two delimited strings /// (as used in a $piece-function) /// /// itm1: first list (as %List or comma-delimited %String) /// itm2: other list (as %List or comma-delimited %String) /// ans : 0 = return a comma-delimited %String with the first match found /// 1 = return a comma-delimited %String with all matches found /// 2 = return a %List with the first match found /// 3 = return a %List with all matches found /// /// return value: according to <ans> argument /// /// Hint: the "$d(var)," part is only needed if the <itm1> argument is /// of %List type and can contain an "undefined" element like the /// second element in $lb(11,,33). /// ClassMethod FindCommonItems(itm1, itm2, ans = 0) { set ptr=0, res="", all=ans#2 set:'$lv(itm1) itm1=$lfs(itm1) set:'$lv(itm2) itm2=$lfs(itm2) while $listnext(itm1,ptr,val) { if $d(val),$lf(itm2,val) { set res=res_$lb(val) quit:'all } } quit $s(ans<2:$lts(res), 1:res) }
Thank you Julius
You are right, but this was based on your original question: "if they share a common element/ value return 1"
But the code is easily enhanced to return all common values.
I haven't put a massive amount of thought into this so it might be garbage for time/space complexity....
Set y = "Red, Green, Orange, Yellow" Set x = "Purple, Black, Yellow, Pink" set x=$ZSTRIP(x,"*W") set y=$ZSTRIP(y,"*W") k ^||members for i=1:1:$L(x,","){ set ^||Members($P(x,",",i),1)="" } for j=1:1:$L(y,","){ set ^||Members($P(y,",",j),2)="" } //Now do a quick traverse of our members set key="" set both="" for { set key=$O(^||Members(key)) quit:key="" set key2="" set key2=$O(^||Members(key,key2)) if ($O(^||Members(key,key2))'="" set both=both_key_"," } w !,"These records are in both lists "_both
Thanks Chris