Welcome › Forums › General PowerShell Q&A › Process and compare records in single collection without repeating
- This topic has 4 replies, 4 voices, and was last updated 1 month, 1 week ago by
Participant.
-
AuthorPosts
-
-
December 5, 2020 at 6:04 am #276765
Hello,
can you advise what should I search for in documentation. I do not know how to call what I am trying to do.
I have a $collection with $record and need to process each to $records a compare it. But I do not want to compare same records and repeat the comparison.
Dummy example of code:PowerShell123456789101112foreach ($record in $collection) {$start = $record.time$label1 = $record.labelforeach ($otherrecord in $collection) {$end = $otherrecord.time$label2 = $otherrecord.label$howlong = (New-TimeSpan -Start $start -End $end).totalhoursif ($howlong -gt 24) {write-host "$label1 and $label2 with more than 24 hours time difference."}}}With the code above, it would compare:
A-A (do not want)
A-B
A-C
B-A (do not want)
B-B (do not want)
B-C
C-A (do not want)
C-B (do not want)
C-C (do not want)It does not matter with 3 records, but I have collection with 80 000+ records. Is there a function or some trick for this? What should I look for?
Thank you
Honza
-
This topic was modified 1 month, 2 weeks ago by
Honza.
-
This topic was modified 1 month, 2 weeks ago by
-
December 8, 2020 at 2:21 pm #277725
How about this?
PowerShell12345foreach ($item in $collection){$collection |Where-Object {($_.time - $item.time).TotalHours -gt 24} |foreach-object {"{0} and {1} with more than 24 hours" -f $item.label, $_.label}} -
December 8, 2020 at 3:29 pm #277737
You have two sources with matching labels? Normally you would want to do some kind of join operation on the other recordset (e.g. Label) and build an object:
PowerShell123456789101112131415161718$record = @()$record += [pscustomobject]@{Label='A-A';Time=(Get-Date)}$record += [pscustomobject]@{Label='A-B';Time=(Get-Date)}$otherrecord = @()$otherrecord += [pscustomobject]@{Label='A-A';Time=(Get-Date).AddDays(2)}$otherrecord += [pscustomobject]@{Label='A-B';Time=(Get-Date).AddHours(2)}$results = foreach ($r in $record) {$match = $otherRecord | Where{$_.Label -eq $r.Label}$r | Select-Object Label,@{Name='StartTime';Expression={$_.Time}},@{Name='EndTime';Expression={$match.Time}},@{Name='Hours';Expression={[math]::Round((New-TimeSpan -Start $_.Time -End $match.Time).TotalHours)}}}$results | Where{$_.Hours -gt '24'}Once you have the object, you can execute a filter on the results:
PowerShell12345678910111213PS C:\Users\rasim> $resultsLabel StartTime EndTime Hours----- --------- ------- -----A-A 12/8/2020 3:20:14 PM 12/10/2020 3:20:14 PM 48A-B 12/8/2020 3:20:14 PM 12/8/2020 5:20:14 PM 2PS C:\Users\rasim> c:\Users\rasim\Desktop\temp.ps1Label StartTime EndTime Hours----- --------- ------- -----A-A 12/8/2020 3:25:52 PM 12/10/2020 3:25:52 PM 48While you can output a string or log, you are then reading it manually. If you use an object approach, you can see all of that data and can do comparisons and exports such as a csv.
-
December 8, 2020 at 3:45 pm #277749
To me it is simplest to use a Queue object. You can Dequeue() (remove) the first object during each run to ensure no repeats.
PowerShell12345678910$queue = [System.Collections.Queue]::new($collection)while ($queue.Count) {$top = $queue.Dequeue()$queue.ToArray() | Foreach-Object {if (($top.Time - $_.Time).Duration().TotalSeconds -gt 86400) {"{0} and {1} with more than 24 hours time difference" -f $top.label,$_.Label}}}This is not going to be an efficient process without have presorted data or using another tool built for bulk comparisons/joins.
-
December 10, 2020 at 12:11 pm #278463
Thank you guys.
I think I found solution on my own. It is primitive, but it works.
PowerShell1234567891011$collection2 = $collection1$collection2 = {$collection2}.invoke()foreach ($collrow1 in $collection1) {.....if ($null -ne $collection2) {$collection2.RemoveAt(0)foreach ($collrow2 in $collection2) {... compare values ...}}}Thank you all. I am going to check your ideas anyway.
Honza
-
-
AuthorPosts
- You must be logged in to reply to this topic.