{"id":8008,"date":"2014-10-27T06:00:00","date_gmt":"2014-10-27T13:00:00","guid":{"rendered":"http:\/\/www.sapien.com\/blog\/?p=8008"},"modified":"2014-11-04T11:48:25","modified_gmt":"2014-11-04T19:48:25","slug":"get-duplicates-or-unique-items","status":"publish","type":"post","link":"https:\/\/dev.sapien.com\/blog\/2014\/10\/27\/get-duplicates-or-unique-items\/","title":{"rendered":"Get-Duplicates (or Unique items)"},"content":{"rendered":"<p>I take a lot of free online coding classes, mainly from Coursera and Udacity, and I\u2019ve picked up a lot of programming tricks in other languages that are easy translated to Windows PowerShell.<\/p>\n<p>In a Java class on Udacity, I learned a cool way to find duplicates in any collection. It uses the fact that the keys in hash tables must be unique. The parser throw an \u201cItem has already been added\u201d error if you try to add a key that\u2019s already in the hash table.<\/p>\n<p>In this example, I try to add \u201cDay\u201d to a hash table that already has an \u201cDay\u201d key. The value is arbitrary.<\/p>\n<p>&nbsp;<\/p>\n<pre>    <span style=\"color: #8b0000;\">$hash<\/span> <span style=\"color: #0000ff;\">=<\/span><span style=\"color: #000000;\"> @{ Day <\/span><span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #ff0000;\">\"Wednesday\"<\/span><span style=\"color: #000000;\">; Weather <\/span><span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #ff0000;\">\"Sunny\"<\/span><span style=\"color: #000000;\"> }\r\n    <\/span><span style=\"color: #8b0000;\">$hash<\/span><span style=\"color: #000000;\">.Add(<\/span><span style=\"color: #ff0000;\">\"Day\"<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #ff0000;\">\"Friday\"<\/span><span style=\"color: #000000;\">)<\/span><\/pre>\n<p>&nbsp;<\/p>\n<pre>    <span style=\"color: #696969;\">ERROR<\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\"> Exception calling <\/span><span style=\"color: #ff0000;\">\"Add\"<\/span><span style=\"color: #000000;\"> with <\/span><span style=\"color: #ff0000;\">\"2\"<\/span><span style=\"color: #000000;\"> argument(<\/span><span style=\"color: #696969;\">s<\/span><span style=\"color: #000000;\">)<\/span><span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #ff0000;\"><strong>\"Item has already been added.<\/strong> Key \r\n    in dictionary: 'Day'  Key being added: 'Day'\"<\/span><span style=\"color: #696969;\">Test.ps1<\/span><span style=\"color: #000000;\"> (<\/span><span style=\"color: #000000;\">15<\/span><span style=\"color: #000000;\">)<\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\"> ERROR<\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\"> At Line<\/span><span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #000000;\">15<\/span><span style=\"color: #000000;\"> char<\/span><span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #000000;\">1<\/span>\r\n    <span style=\"color: #696969;\">ERROR<\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\"> + <\/span><span style=\"color: #8b0000;\">$hash<\/span><span style=\"color: #000000;\">.Add(<\/span><span style=\"color: #ff0000;\">\"Day\"<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #ff0000;\">\"Friday\"<\/span><span style=\"color: #000000;\">)\r\n    <\/span><span style=\"color: #696969;\">ERROR<\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\"> + ~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n    <\/span><span style=\"color: #696969;\">ERROR<\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\"> + CategoryInfo          <\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\"> NotSpecified<\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\"> (<\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\">) [], MethodInvocationException\r\n    <\/span><span style=\"color: #696969;\">ERROR<\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\"> + FullyQualifiedErrorId <\/span><span style=\"color: #0000ff;\">:<\/span><span style=\"color: #000000;\"> ArgumentException\r\n    <\/span><span style=\"color: #696969;\">ERROR<\/span><span style=\"color: #0000ff;\">:<\/span><\/pre>\n<p>&nbsp;<\/p>\n<p>To detect a duplicate in a small collection, create a hash table and add the items to the hash table as keys.<\/p>\n<pre>    <span style=\"color: #8b0000;\">$hash<\/span> <span style=\"color: #0000ff;\">=<\/span><span style=\"color: #000000;\"> @{ }\r\n    <\/span><span style=\"color: #ff0000;\">\"a\"<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #ff0000;\">\"b\"<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #ff0000;\">\"a\"<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #ff0000;\">\"c\"<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #ff0000;\">\"d\"<\/span> <span style=\"color: #0000ff;\">|<\/span> <span style=\"font-weight: bold; color: #c00000;\">ForEach<\/span><span style=\"color: #000000;\"> { <\/span><span style=\"color: #8b0000;\">$hash<\/span><span style=\"color: #000000;\">.Add(<\/span><span style=\"color: #8b0000;\">$_<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #000000;\">0<\/span><span style=\"color: #000000;\">) }<\/span><\/pre>\n<p>&nbsp;<\/p>\n<p>Use a Try block to add each item as a key with a value of 0. If a MethodInvocationException occurs in the Try block code, instead of erroring out and interrupting the script, it falls in the Catch block. I use the Catch block to save the duplicates in an array.<\/p>\n<pre>    <span style=\"color: #8b0000;\">$Items<\/span> <span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #ff0000;\">\"a\"<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #ff0000;\">\"b\"<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #ff0000;\">\"a\"<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #ff0000;\">\"c\"<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #ff0000;\">\"d\"\r\n<\/span>    <span style=\"color: #8b0000;\">$hash<\/span> <span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #000000;\">@{ }\r\n    <\/span><span style=\"color: #8b0000;\">$duplicates<\/span> <span style=\"color: #0000ff;\">=<\/span><span style=\"color: #000000;\"> @()<\/span><\/pre>\n<p>&nbsp;<\/p>\n<pre>        <span style=\"color: #0000ff;\">foreach<\/span><span style=\"color: #000000;\"> (<\/span><span style=\"color: #8b0000;\">$item<\/span> <span style=\"color: #0000ff;\">in<\/span> <span style=\"color: #8b0000;\">$Items<\/span><span style=\"color: #000000;\">)\r\n        {\r\n            <\/span><span style=\"color: #0000ff;\">try<\/span><span style=\"color: #000000;\">\r\n            {\r\n                <\/span><span style=\"color: #8b0000;\">$hash<\/span><span style=\"color: #000000;\">.add(<\/span><span style=\"color: #8b0000;\">$item<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #000000;\">0<\/span><span style=\"color: #000000;\">)\r\n            }\r\n<\/span>            <span style=\"color: #0000ff;\">catch<\/span><span style=\"color: #000000;\"> [<\/span><span style=\"color: #0000cd;\">System.Management.Automation.MethodInvocationException<\/span><span style=\"color: #000000;\">]\r\n<\/span><span style=\"color: #000000;\">            {\r\n                <\/span><span style=\"color: #8b0000;\">$duplicates<\/span> <span style=\"color: #0000ff;\">+=<\/span> <span style=\"color: #8b0000;\">$item<\/span><span style=\"color: #000000;\">\r\n            }\r\n        }<\/span><\/pre>\n<p>&nbsp;<\/p>\n<p>You can return the duplicates that you saved and\/or the unique items, which are the keys in the hash table.<\/p>\n<pre>    <span style=\"color: #8b0000;\">$hash<\/span><span style=\"color: #000000;\">.keys\r\n    <\/span><span style=\"color: #696969;\">c<\/span>\r\n    <span style=\"color: #696969;\">a<\/span>\r\n    <span style=\"color: #696969;\">d<\/span>\r\n    <span style=\"color: #696969;\">b<\/span><\/pre>\n<p>&nbsp;<\/p>\n<p>For the final version of my little script, I convert the hash table to an ordered dictionary, which preserves the order in which the keys were added. I also allow users to pipe the items to the script by adding the ValueFromPipeline parameter attribute and the Process block that supports it.<\/p>\n<pre><span style=\"color: #008000;\">&lt;#\r\n    .SYNOPSIS\r\n        Gets duplicates or unique values in a collection.\r\n\r\n    .DESCRIPTION\r\n        The Get-Duplicates.ps1 script takes a collection and returns\r\n        the duplicates (by default) or unique members (use the Unique\r\n        switch parameter).\r\n\r\n    .PARAMETER  Items\r\n        Enter a collection of items. You can also pipe the items to\r\n        Get-Duplicates.ps1.\r\n\r\n    .PARAMETER  Unique\r\n        Returns unique items instead of duplicates. By default, Get-Duplicates.ps1\r\n        returns only duplicates.\r\n\r\n    .EXAMPLE\r\n        PS C:\\&gt; .\\Get-Duplicates.ps1 -Items 1,2,3,2,4\r\n        2\r\n\r\n    .EXAMPLE\r\n        PS C:\\&gt; 1,2,3,2,4 | .\\Get-Duplicates.ps1\r\n        2\r\n\r\n    .EXAMPLE\r\n        PS C:\\&gt; .\\Get-Duplicates.ps1 -Items 1,2,3,2,4 -Unique\r\n        1\r\n        2\r\n        3\r\n        4\r\n\r\n    .INPUTS\r\n        System.Object[]\r\n\r\n    .OUTPUTS\r\n        System.Object[]\r\n\r\n    .NOTES\r\n    ===========================================================================\r\n     Created with:     SAPIEN Technologies, Inc., PowerShell Studio 2014 v4.1.72\r\n     Created on:       10\/15\/2014 9:34 AM\r\n     Created by:       June Blender (juneb)\r\n#&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">param<\/span><span style=\"color: #000000;\">\r\n(\r\n    [<\/span><span style=\"color: #4682b4;\">Parameter<\/span><span style=\"color: #000000;\">(Mandatory <\/span><span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #8b0000;\">$true<\/span><span style=\"color: #000000;\">,\r\n               ValueFromPipeline <\/span><span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #8b0000;\">$true<\/span><span style=\"color: #000000;\">)]\r\n    [<\/span><span style=\"color: #0000cd;\">Object<\/span><span style=\"color: #000000;\">[]]\r\n    <\/span><span style=\"color: #8b0000;\">$Items<\/span><span style=\"color: #000000;\">,\r\n    \r\n    [<\/span><span style=\"color: #4682b4;\">Parameter<\/span><span style=\"color: #000000;\">(Mandatory <\/span><span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #8b0000;\">$false<\/span><span style=\"color: #000000;\">)]\r\n    [<\/span><span style=\"color: #0000cd;\">Switch<\/span><span style=\"color: #000000;\">]\r\n    <\/span><span style=\"color: #8b0000;\">$Unique<\/span><span style=\"color: #000000;\">\r\n)\r\n<\/span><span style=\"color: #0000ff;\">Begin<\/span><span style=\"color: #000000;\">\r\n{\r\n    <\/span><span style=\"color: #8b0000;\">$hash<\/span> <span style=\"color: #0000ff;\">=<\/span><span style=\"color: #000000;\"> [<\/span><span style=\"color: #0000cd;\">ordered<\/span><span style=\"color: #000000;\">]@{ }\r\n    <\/span><span style=\"color: #8b0000;\">$duplicates<\/span> <span style=\"color: #0000ff;\">=<\/span><span style=\"color: #000000;\"> @()\r\n}\r\n<\/span><span style=\"color: #0000ff;\">Process<\/span><span style=\"color: #000000;\">\r\n{\r\n    <\/span><span style=\"color: #0000ff;\">foreach<\/span><span style=\"color: #000000;\"> (<\/span><span style=\"color: #8b0000;\">$item<\/span> <span style=\"color: #0000ff;\">in<\/span> <span style=\"color: #8b0000;\">$Items<\/span><span style=\"color: #000000;\">)\r\n    {\r\n        <\/span><span style=\"color: #0000ff;\">try<\/span><span style=\"color: #000000;\">\r\n        {\r\n            <\/span><span style=\"color: #8b0000;\">$hash<\/span><span style=\"color: #000000;\">.add(<\/span><span style=\"color: #8b0000;\">$item<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #000000;\">0<\/span><span style=\"color: #000000;\">)\r\n        }\r\n        <\/span><span style=\"color: #0000ff;\">catch<\/span><span style=\"color: #000000;\"> [<\/span><span style=\"color: #0000cd;\">System.Management.Automation.MethodInvocationException<\/span><span style=\"color: #000000;\">]\r\n        {\r\n            <\/span><span style=\"color: #8b0000;\">$duplicates<\/span> <span style=\"color: #0000ff;\">+=<\/span> <span style=\"color: #8b0000;\">$item<\/span><span style=\"color: #000000;\">\r\n        }\r\n    }\r\n}\r\n<\/span><span style=\"color: #0000ff;\">End<\/span><span style=\"color: #000000;\">\r\n{\r\n    <\/span><span style=\"color: #0000ff;\">if<\/span><span style=\"color: #000000;\"> (<\/span><span style=\"color: #8b0000;\">$unique<\/span><span style=\"color: #000000;\">)\r\n    {\r\n        <\/span><span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #8b0000;\">$hash<\/span><span style=\"color: #000000;\">.keys\r\n        \r\n    }\r\n    <\/span><span style=\"color: #0000ff;\">elseif<\/span><span style=\"color: #000000;\"> (<\/span><span style=\"color: #8b0000;\">$duplicates<\/span><span style=\"color: #000000;\">)\r\n    {\r\n        <\/span><span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #8b0000;\">$duplicates<\/span><span style=\"color: #000000;\">\r\n    }\r\n}<\/span><\/pre>\n<p>&nbsp;<\/p>\n<p>Remember that qualification about <em>small<\/em> collections of items? This strategy is a little programming trick that is not optimized for large data sets. For those, stick with Microsoft.PowerShell.Utility\\Get-Unique and other optimized methods.<\/p>\n<p><i>June Blender is a technology evangelist at SAPIEN Technologies, Inc. You can reach her at <a href=\"mailto:juneb@sapien.com\">juneb@sapien.com<\/a> or follow her on Twitter at <a href=\"https:\/\/twitter.com\/juneb_get_help\">@juneb_get_help<\/a>.<\/i><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I take a lot of free online coding classes, mainly from Coursera and Udacity, and I\u2019ve picked up a lot of programming tricks in other languages that are easy translated to Windows PowerShell. In a Java class on Udacity, I learned a cool way to find duplicates in any collection. It uses the fact that [&hellip;]<\/p>\n","protected":false},"author":31,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[25],"tags":[934,28],"class_list":["post-8008","post","type-post","status-publish","format-standard","hentry","category-windows-powershell","tag-juneb","tag-powershell"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/8008","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/comments?post=8008"}],"version-history":[{"count":6,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/8008\/revisions"}],"predecessor-version":[{"id":8082,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/8008\/revisions\/8082"}],"wp:attachment":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/media?parent=8008"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/categories?post=8008"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/tags?post=8008"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}