ericalle
ericalle

Reputation: 251

How can you select unique objects based on two properties of an object in powershell?

I have an array of Objects that have 6 properties. That look like this:

$csvData
CURRENT DATE AND TIME : 07/10/2015 08:17:17 CST
USER NAME             : userName
COMPUTER NAME         : computerName
IP ADDRESS            : 192.168.1.1
LOGON SERVER          : logonServer
LOGON/OFF             : logon

I want to create an array of objects where username and computer name are not duplicated. How can I get only the unique username/computername combo in powershell? Ultimately I would like to remove all duplicates and add a property 'Count' that keeps track of how many duplicates there are.

I have tried:

$csvDataUnique = $csvData | Select-Object 'User Name','Computer Name' -Unique
$csvDataUnique = $csvData | sort -Property 'User Name' | Get-Unique

Upvotes: 25

Views: 40541

Answers (6)

Joel
Joel

Reputation: 125

The other answers didn't retain the rest of the properties in the final output. This should work for you:

$csvDataUnique = $csvData | Group-Object -Property 'User Name', 'Computer Name' | ForEach-Object { $_.Group[0] }

Upvotes: 6

Alex_P
Alex_P

Reputation: 2952

An alternative option is to use Get-Unique. It was quite helpful in my situation when I wanted to select objects based on a unique property without some extensive foreach-loop.

$csvData | Sort-Object 'User Name', 'Computer Name' | Get-Unique -AsString

The object needs to be sorted because Get-Unique compares the strings adjacent to each other. Additionally, the comparison is case-sensitive.

Upvotes: 3

R. McGee
R. McGee

Reputation: 406

Very similar to Mathias' answer, but will have all of the columns in the output:

$csvDataUnique = $csvData | 
  Group-Object 'User Name','Computer Name' | 
  %{ $_.Group | Select 'User Name','Computer Name' -First 1} | 
  Sort 'User Name','Computer Name' 

Upvotes: 26

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174575

You can use Group-Object to group by multiple properties:

$Uniqs = $csvData | Group -Property "USER NAME","COMPUTER NAME" -NoElement | Select -Expand Name

Upvotes: 1

Benjamin Hubbard
Benjamin Hubbard

Reputation: 2917

You can create a custom property with your Select-Object. So you were pretty close already. Try this:

Select-Object @{Label = "Index"; Expression = {"$($_.'User Name') $($_.'Computer Name')"} } -Unique

It basically combines the two fields into a single string and sorts unique on that. I called the field "Index" but it could be called anything.

Upvotes: 6

mjolinor
mjolinor

Reputation: 68293

I usually resort to using a hash table, and joined property values for the keys for that kind of task:

$CSVDataUnique = @{}

$csvData | foreach {
 $CSVDataUnique["$_.'User Name'\$_.'Computer Name'"]++
}

Upvotes: 1

Related Questions