Reputation: 165
The Dean of Students at the school I work at has asked me to import the daily attendance and class attendance into our SIS from the LMS. This was easy, until I realized that there is cross contamination. For example, if John's parents emailed to let the school know that John is sick on 10/24/2017. The Dean marked John as absent for the day, and then his teachers marked him absent in each of his classes. As a result, John has a daily attendance record on 10/24/2017 AND 6 class absence records for each of the classes he missed that day.
They won't change their process, so I need a way to remove Class absences from the import file for students that also have Daily Absences on the same date.
I have two arrays of PSObject
s containing objects with different attributes.
The objects in the Daily Attendance array, $dailyRecords
, all have the attributes, StudentID
, Date
, Type
, and Description
.
The Class Attendance array, $classRecords
, has objects have the same attributes as the first one, and CourseID
and SectionNo
, in addition.
I've tried a few ways to remove the extra class records from the $classRecords
array:
$classRecords | Where-Object { $_.Date, $_.StudentID -notin $dailyRecords}
, based on this answer, but that gave me all of the ~1600 class records.I tried the following, based on this answer, but got no results (I think) the objects in the arrays reference different types...? Not sure. (I just used the following, I didn't include the foreach
part. Maybe that was the issue... I'll try it tonight and update.)
Compare-Object $classRecords $dailyRecords |
Where-Object {$_.SideIndicator -ne "=="} |
Select-Object -ExpandProperty InputObject
I also tried a variation on #2:
Compare-Object $classRecords $dailyRecords -Property Date, StudentID |
Where-Object {$_.SideIndicator -ne "=="}
# I had to remove the last line, as InputObject was no longer defined.
But that resulted in me losing all the other attributes that I need.
This answer results in what is closest to what I want to do, but I can't figure out how to modify it to my needs.
How do I remove the duplicated data from the class attendance without losing any information about the objects themselves?
Upvotes: 1
Views: 1092
Reputation: 7163
I would do something like this:
$dailyRecords = @(
[PSCustomObject]@{StudentId='1'; Date='10/22/2017'; Type='type data'; Description='desc data'}
[PSCustomObject]@{StudentId='1'; Date='10/23/2017'; Type='type data'; Description='desc data'}
[PSCustomObject]@{StudentId='1'; Date='10/24/2017'; Type='type data'; Description='desc data'}
[PSCustomObject]@{StudentId='2'; Date='10/24/2017'; Type='type data'; Description='desc data'}
[PSCustomObject]@{StudentId='3'; Date='10/23/2017'; Type='type data'; Description='desc data'}
[PSCustomObject]@{StudentId='3'; Date='10/24/2017'; Type='type data'; Description='desc data'}
)
$classRecords = @(
[PSCustomObject]@{StudentId='1'; Date='10/19/2017'; Type='type data'; Description='desc data'; CourseId='1'; SectionNum='1'}
[PSCustomObject]@{StudentId='1'; Date='10/23/2017'; Type='type data'; Description='desc data'; CourseId='2'; SectionNum='2'}
[PSCustomObject]@{StudentId='1'; Date='10/24/2017'; Type='type data'; Description='desc data'; CourseId='3'; SectionNum='3'}
[PSCustomObject]@{StudentId='4'; Date='10/24/2017'; Type='type data'; Description='desc data'; CourseId='1'; SectionNum='1'}
)
$attendanceRecords = @{}
foreach ($record in $dailyRecords)
{
$key = $record.StudentId + ';' + $record.Date
$attendanceRecords.Add($key, $record)
}
foreach ($record in $classRecords)
{
$key = $record.StudentId + ';' + $record.Date
if (-not $attendanceRecords.ContainsKey($key))
{
$tempRecord = [PSCustomObject]($record | Select-Object StudentId, Date, Type, Description)
$attendanceRecords.Add($key, $tempRecord)
}
}
$attendanceRecords.Values | Sort -Property StudentId, Date | ft
and give output:
StudentId Date Type Description
--------- ---- ---- -----------
1 10/19/2017 type data desc data
1 10/22/2017 type data desc data
1 10/23/2017 type data desc data
1 10/24/2017 type data desc data
2 10/24/2017 type data desc data
3 10/23/2017 type data desc data
3 10/24/2017 type data desc data
4 10/24/2017 type data desc data
which is all the Daily and each Class which is not already in Daily per your original requirement.
Upvotes: 1
Reputation: 23663
$classRecords | Where {$c = $_; $dailyRecords | Where {$_.StudentID -ne $c.StudentID -and $_.Date -ne $c.Date}}
Upvotes: 0
Reputation: 8893
$ret = @()
foreach($classRecord in $classRecords)
{
foreach($dailyRecord in $dailyRecords)
{
if($classRecord.CourseID -eq $dailyRecord.CourseID) # modify this to match your conditions
{
$obj = New-Object PsObject
foreach($classProp in $classRecord.PsObject.Properties) # do this loop for $dailyRecord if you want those properties as well
{
$obj | Add-Member -NotePropertyName $prop.Name -NotePropertyValue $prop.Value
}
$ret += $obj
}
}
}
# output the array
$ret
After that, you might have to filter the dupes out of $ret
Upvotes: 0
Reputation: 17462
try Something like this:
$classrecords=@(
[pscustomobject]@{Date='2017-10-24';StudentID=1},
[pscustomobject]@{Date='2017-10-25';StudentID=2},
[pscustomobject]@{Date='2017-10-26';StudentID=3}
)
$dailyRecords=@(
[pscustomobject]@{Date='2017-10-24';StudentID=1},
[pscustomobject]@{Date='2017-10-23';StudentID=2},
[pscustomobject]@{Date='2017-10-26';StudentID=5}
)
$classrecords | % {$current=$_; $dailyRecords | % { if ($_.Date -eq $current.Date -and $_.StudentID -eq $current.StudentID) {$current}}}
Upvotes: 0