{"id":66413,"date":"2006-09-22T09:02:00","date_gmt":"2006-09-22T09:02:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2006\/09\/22\/how-can-i-verify-that-all-the-items-in-a-list-also-appear-in-another-list\/"},"modified":"2006-09-22T09:02:00","modified_gmt":"2006-09-22T09:02:00","slug":"how-can-i-verify-that-all-the-items-in-a-list-also-appear-in-another-list","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-verify-that-all-the-items-in-a-list-also-appear-in-another-list\/","title":{"rendered":"How Can I Verify That All the Items in a List Also Appear in Another List?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> \n<P>Hey, Scripting Guy! I have a dumb question for you: If I have two lists how can I verify that all the items in list 2 can be found in list 1?<BR><BR>&#8212; SS<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" border=\"0\" alt=\"Script Center\" align=\"right\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" height=\"288\"><\/A> \n<P>Hey, SS. Trust us; we\u2019ve heard sillier questions. For example, awhile back the Scripting Son came downstairs on a Saturday morning to find the Scripting Dad eating breakfast. \u201cWhat\u2019s that?\u201d he said, pointing to his father\u2019s bowl.<\/P>\n<P>\u201cOatmeal.\u201d<\/P>\n<P>\u201cIsn\u2019t oatmeal supposed to have milk on it?\u201d asked the Scripting Son.<\/P>\n<P>\u201cRegular oatmeal, like the kind Grandma makes, does,\u201d said the Scripting Dad. \u201cBut this is instant oatmeal: you just add hot water to instant oatmeal.\u201d<\/P>\n<P>\u201cOh,\u201d said the Scripting Son. \u201cMaybe that\u2019s why I don\u2019t like instant oatmeal.\u201d<\/P>\n<P>As it turns out years ago, when he was little, the Scripting Son decided to make himself some instant oatmeal. He took the package out of the box, poured it into a bowl, then added cold milk. Not too surprisingly, he didn\u2019t really like it.<\/P>\n<TABLE id=\"EAD\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P><B>Note<\/B>. No, the Scripting Dad didn\u2019t poke fun at the Scripting Son. After all, the Scripting Dad didn\u2019t want to be reminded of the time he and the Scripting Son were driving home from a baseball game when the Scripting Dad was suddenly struck by a terrible thought. \u201cUh-oh,\u201d he said as they cruised down the road. \u201cI can\u2019t remember whether or not I took my keys out of the bat bag.\u201d<\/P>\n<P>\u201cYou mean the keys you used to start the car, the ones that are in the ignition right now?\u201d asked the Scripting Son.<\/P>\n<P>Yes, those keys.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Needless to say, SS, when it comes to the silliest questions of all time, well, yours just doesn\u2019t stack up all that well. However, and if it\u2019s any consolation, your question <I>has<\/I> officially become one of the questions answered in this column:<\/P><PRE class=\"codeSample\">Const TextMode = 1<\/p>\n<p>arrList1 = Array(&#8220;a&#8221;,&#8221;b&#8221;,&#8221;c&#8221;,&#8221;d&#8221;,&#8221;e&#8221;,&#8221;f&#8221;)\narrList2 = Array(&#8220;a&#8221;,&#8221;b&#8221;,&#8221;e&#8221;,&#8221;g&#8221;,&#8221;h&#8221;)<\/p>\n<p>Set objDictionary = CreateObject(&#8220;Scripting.Dictionary&#8221;)\nobjDictionary.CompareMode = TextMode<\/p>\n<p>For Each strValue in arrList1\n    If Not objDictionary.Exists(strValue) Then\n        objDictionary.Add strValue, strValue\n    End If\nNext<\/p>\n<p>For Each strValue2 in arrList2\n    If Not objDictionary.Exists(strValue2) Then\n        strNotFound = strNotFound &amp; strValue2 &amp; vbCrLf\n    End If\nNext<\/p>\n<p>If strNotFound &lt;&gt; &#8220;&#8221; Then\n    Wscript.Echo &#8220;Items in list 2 that are not in list 1:&#8221; &amp; vbCrLf &amp; strNotFound \nEnd If\n<\/PRE>\n<P>Let\u2019s see if we can figure out how this works. The script starts out by defining a constant named TextMode and setting the value to 1; we\u2019ll use this constant later on to tell our Dictionary object to perform case-insensitive searches. We do that because, by default, the Dictionary object sees <I>A<\/I> (uppercase) and <I>a<\/I> (lowercase) as totally separate items. If you\u2019d prefer to do a case-sensitive search (where <I>a<\/I> and <I>A<\/I> are considered different characters), then leave out this line and the line of code where we configure the <B>CompareMode <\/B>property.<\/P>\n<TABLE id=\"EEE\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. And if you\u2019d like to know more about the difference between case-sensitive and case-insensitive searches, take a peek at the scripting puzzle <A href=\"http:\/\/null\/technet\/scriptcenter\/funzone\/puzzle\/questions\/aug2506.mspx\"><B>Everyone is Special \u2026 Except You, James<\/B><\/A>.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>After defining the constant we then set up two very simple arrays, arrays that represent our two lists. The array arrList1 consists of the following items:<\/P><PRE class=\"codeSample\">a\nb\nc\nd\ne\nf\n<\/PRE>\n<P>Meanwhile, the array arrList2 consists of <I>these<\/I> items:<\/P><PRE class=\"codeSample\">a\nb\ne\ng\nh\n<\/PRE>\n<P>Our task is to figure out whether there are any items in arrList2 that are <I>not<\/I> in arrList1.<\/P>\n<P>How do we plan on doing that? Why, by using the <B>Scripting.Dictionary<\/B> object, of course. That\u2019s why we use these two lines of code to create an instance of the Dictionary object and then set the CompareMode to the constant TextMode (which will result in case-insensitive searches):<\/P><PRE class=\"codeSample\">Set objDictionary = CreateObject(&#8220;Scripting.Dictionary&#8221;)\nobjDictionary.CompareMode = TextMode\n<\/PRE>\n<P>Good question: why are we using the Dictionary object anyway? We opted to go this route primarily because it\u2019s very tedious to search for specific items in a VBScript array. Suppose we want to know if the value <I>z<\/I> appears in the array. We can\u2019t just say, \u201cHey, array: do you have a <I>z<\/I> anywhere?\u201d Instead, we have to loop through and individually check each item in that array. And then we have to repeat that process for the next value, and the value after that, and \u2013 well, you get the idea. With the Dictionary object, however, we <I>can<\/I> just ask it whether or not it has any <I>z<\/I>\u2019s, a process we\u2019ll explain momentarily.<\/P>\n<P>Before we can do that, however, we need to grab all the elements in arrList1 and get them into the Dictionary. That\u2019s what these lines of code are for:<\/P><PRE class=\"codeSample\">For Each strValue in arrList1\n    If Not objDictionary.Exists(strValue) Then\n        objDictionary.Add strValue, strValue\n    End If\nNext\n<\/PRE>\n<P>As you can see, all we\u2019re doing here is looping through the collection of values stored in the array arrList1. For each of these values we then use the <B>Exists<\/B> method to determine whether or not the value is already in the Dictionary:<\/P><PRE class=\"codeSample\">If Not objDictionary.Exists(strValue) Then\n<\/PRE>\n<P>Is that important? Well, it could be; after all, the Dictionary object won\u2019t accept duplicate entries. Because the best way to avoid duplicate entries is to check each value before we add it to the Dictionary we use the following line of code to determine whether or not our Dictionary object already has an entry for <I>a<\/I>, the first item in arrList1:<\/P><PRE class=\"codeSample\">If Not objDictionary.Exists(strValue) Then\n<\/PRE>\n<P>Yes, we know: the syntax \u2013 <B>If Not objDictionary.Exists(strValue)<\/B> \u2013 is a little clumsy. But all we\u2019re saying is this: let us know if you <I>don\u2019t<\/I> have an entry for the letter <I>a<\/I>. If you already have a key named <I>a<\/I> that\u2019s fine; we\u2019ll just loop around and check the next item in the list. If you <I>don\u2019t<\/I> have an <I>a<\/I>, then we\u2019re going to use this line of code to add <I>a<\/I> to the Dictionary, setting both the Dictionary key and value to, well, <I>a<\/I>:<\/P><PRE class=\"codeSample\">objDictionary.Add strValue, strValue\n<\/PRE>\n<TABLE id=\"E6G\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. What\u2019s the difference between a Dictionary key and a value? Tsk, tsk, tsk: you haven\u2019t been reading <A href=\"http:\/\/null\/technet\/scriptcenter\/resources\/begin\/ss0906.mspx\"><B>Sesame Script<\/B><\/A> each month, have you?<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>When we\u2019re all done our Dictionary will include the following items, which just happen to be the same items found in arrList1:<\/P><PRE class=\"codeSample\">a\nb\nc\nd\ne\nf\n<\/PRE>\n<P>We\u2019re now ready to start looping through the items in the second list (arrList2) and determine whether or not those items can be found in arrList1. To do that we set up another For Each loop, this one looping through the array arrList2:<\/P><PRE class=\"codeSample\">For Each strValue2 in arrList2\n    If Not objDictionary.Exists(strValue2) Then\n        strNotFound = strNotFound &amp; strValue2 &amp; vbCrLf\n    End If\nNext\n<\/PRE>\n<P>Nothing too fancy here, either. Again, we\u2019re using the <B>Exists<\/B> method to determine whether or not the first value in arrList2 can be found in the Dictionary. As it turns out, the first value (<I>a<\/I>) actually <I>does<\/I> exist in the Dictionary. That means that <I>a<\/I> must also exist in arrList1, which, in turn, means we don\u2019t care about it. (Remember, we\u2019re only looking for items in arrList2 that <I>aren\u2019t<\/I> in arrList1.) With that in mind, we loop around and try the next item in the list.<\/P>\n<P>Eventually we\u2019re going to run into an item \u2013 <I>g<\/I> \u2013 that <I>isn\u2019t<\/I> in the Dictionary. That will trigger this line of code:<\/P><PRE class=\"codeSample\">strNotFound = strNotFound &amp; strValue2 &amp; vbCrLf\n<\/PRE>\n<P>Here we\u2019re assigning a value to a variable named strNotFound. To be more precise, we\u2019re assigning this variable its existing value (which, at the start of the script, is nothing) plus the value of the item we failed to find in the Dictionary (<I>g<\/I>) plus a carriage return-linefeed (vbCrLf). In other words, after failing to find <I>g<\/I> in the Dictionary, strNotFound will be equal to this:<\/P><PRE class=\"codeSample\">g\n<\/PRE>\n<P>We then loop around and try the next item in the list; that\u2019s <I>h<\/I>, which doesn\u2019t appear in the Dictionary either. We thus append this value and a carriage return-linefeed to the existing value of strNotFound, meaning strNotFound is now equal to this:<\/P><PRE class=\"codeSample\">g\nh\n<\/PRE>\n<P>You get the idea. If there were more values in arrList2 we\u2019d simply continue this process until we\u2019ve tested for the existence of each and every one.<\/P>\n<P>And <I>then<\/I> what happens, after we\u2019ve tested each and every one of those values? This happens:<\/P><PRE class=\"codeSample\">If strNotFound &lt;&gt; &#8220;&#8221; Then\n    Wscript.Echo &#8220;Items in list 2 that are not in list 1:&#8221; &amp; vbCrLf &amp; strNotFound \nEnd If\n<\/PRE>\n<P>Here we\u2019re simply checking the value of strNotFound. If strNotFound is an empty string that means that all the values in arrList2 were found in arrList1; therefore, we don\u2019t do anything. If strNotFound is <I>not<\/I> an empty string that means we found at least one value in arrList2 that doesn\u2019t appear in arrList1. Consequently, we echo back a message similar to this:<\/P><PRE class=\"codeSample\">Items in list 2 that are not in list 1:\ng\nh\n<\/PRE>\n<P>Needless to say, <I>g<\/I> and <I>h<\/I> just happen to be the two items in list 2 that don\u2019t appear in list 1. Pretty cool, huh?<\/P>\n<P>We hope that helps, SS. And remember, there\u2019s no such thing as a dumb question, not even the age-old query, \u201cDoes this dress make me look fat?\u201d The truth is, that question isn\u2019t dumb; what\u2019s dumb would be giving an honest and thoughtful <I>answer<\/I> to that question. (Not that any of the Scripting Guys have ever done that, mind you.)<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I have a dumb question for you: If I have two lists how can I verify that all the items in list 2 can be found in list 1?&#8212; SS Hey, SS. Trust us; we\u2019ve heard sillier questions. For example, awhile back the Scripting Son came downstairs on a Saturday morning to [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[18,3,4,5],"class_list":["post-66413","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-arrays-hash-tables-and-dictionary-objects","tag-scripting-guy","tag-scripting-techniques","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I have a dumb question for you: If I have two lists how can I verify that all the items in list 2 can be found in list 1?&#8212; SS Hey, SS. Trust us; we\u2019ve heard sillier questions. For example, awhile back the Scripting Son came downstairs on a Saturday morning to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/66413","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=66413"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/66413\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=66413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=66413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=66413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}