You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修正CSV对账去重空值并实现班级名单增减精准检测?

改进MS Teams班级名单对比脚本

需求说明

我之前用一段PowerShell代码检测班级名单的新增/变更,但现在需要优化:

  1. 新增移除检测能力:对比两个CSV文件,能分别输出「从旧名单中移除的条目」和「新名单中新增的条目」
  2. 按班级+用户组合对比:同一个学生可能在多个班级,必须以TeamDesc+UserPrincipalName的组合作为唯一标识,避免跨班级误判
  3. 预处理CSV数据:自动去除重复条目和空值,保证对账准确性

原代码如下:

$set = [System.Collections.Generic.HashSet[string]]::new(
    [string[]] (Import-CSV -Path stundent.csv).UserPrincipalName,
    [System.StringComparer]::InvariantCultureIgnoreCase
)
Import-Csv ad.csv | Where-Object { $set.Add($_.UserPrincipalName) } |
    Export-Csv path\to\output.csv -NoTypeInformation

示例数据

Source1.csv(旧名单)

TeamDescUserPrincipalName姓名
Team 1student1@domain.comjohn smith
Team 1student2@domain.comnancy drew
Team 2student3@domain.comharvey dent
Team 3student1@domain.comjohn smith

Source2.csv(新名单)

TeamDescUserPrincipalName姓名
Team 1student2@domain.comnancy drew
Team 2student3@domain.comharvey dent
Team 2student4@domain.comtim tams
Team 3student1@domain.comjohn smith

预期输出

Export1.csv(移除的条目:Source1有但Source2没有)

TeamDescUserPrincipalName姓名
Team 1student1@domain.comjohn smith

Export2.csv(新增的条目:Source2有但Source1没有)

TeamDescUserPrincipalName姓名
Team 2student4@domain.comtim tams

解决方案代码

1. 通用预处理函数(去重、过滤空值)

先定义一个函数处理CSV数据,确保每个TeamDesc+UserPrincipalName组合唯一,同时过滤掉关键字段为空的条目:

function Clean-CsvData {
    param(
        [Parameter(Mandatory)]
        [string]$CsvPath
    )
    # 导入CSV并过滤空值,然后按组合去重
    Import-Csv -Path $CsvPath |
        Where-Object { $_.TeamDesc -and $_.UserPrincipalName } |
        Group-Object -Property TeamDesc, UserPrincipalName |
        ForEach-Object { $_.Group[0] }
}

2. 检测新增/移除的核心脚本

# 定义文件路径
$oldCsvPath = "Source1.csv"
$newCsvPath = "Source2.csv"
$removedOutputPath = "Export1.csv"
$addedOutputPath = "Export2.csv"

# 预处理两个CSV文件
$oldData = Clean-CsvData -CsvPath $oldCsvPath
$newData = Clean-CsvData -CsvPath $newCsvPath

# 创建HashSet存储旧数据的唯一组合(TeamDesc+UserPrincipalName)
$oldSet = [System.Collections.Generic.HashSet[string]]::new(
    $oldData | ForEach-Object { "$($_.TeamDesc)|$($_.UserPrincipalName)" },
    [System.StringComparer]::InvariantCultureIgnoreCase
)

# 创建HashSet存储新数据的唯一组合
$newSet = [System.Collections.Generic.HashSet[string]]::new(
    $newData | ForEach-Object { "$($_.TeamDesc)|$($_.UserPrincipalName)" },
    [System.StringComparer]::InvariantCultureIgnoreCase
)

# 导出移除的条目:旧数据中不在新数据里的组合
$oldData | Where-Object {
    -not $newSet.Contains("$($_.TeamDesc)|$($_.UserPrincipalName)")
} | Export-Csv -Path $removedOutputPath -NoTypeInformation -Encoding UTF8

# 导出新增的条目:新数据中不在旧数据里的组合
$newData | Where-Object {
    -not $oldSet.Contains("$($_.TeamDesc)|$($_.UserPrincipalName)")
} | Export-Csv -Path $addedOutputPath -NoTypeInformation -Encoding UTF8

代码说明

  • 预处理函数:通过Group-Object按TeamDesc和UserPrincipalName组合分组,只保留每组第一条数据实现去重;同时过滤掉关键字段为空的条目,避免无效数据干扰。
  • HashSet组合键:用|分隔TeamDesc和UserPrincipalName作为唯一标识,确保同一个学生在不同班级的条目被视为独立项。
  • 双向对比:通过两个HashSet分别存储新旧数据的组合键,实现高效的存在性检查,快速筛选出新增和移除的条目。

内容的提问来源于stack exchange,提问作者Tyler Laidler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 18:40:39