首页 > 解决方案 > 将 CSV 与包含另一个 CSV 的两列的数组进行比较

问题描述

我有两个 CSV。CSV1 由 3 列组成:名称、用户名、主组;CSV2 由 4 列组成:名称、用户名、部门、​​部门两个 CSV 都按名称列排序。

我需要将来自这两个 CVS 的数据,特别是来自 CVS2 的DepartmentDivision与来自 CSV1 的MainGroup进行比较。然后将结果导出到 CVS 文件中,其中将包含Name、Username、MatchedGroup。因此,在结果 CVS 的第三列中,我想保留DepartmentDivisionMainGroup列的比较结果。即,如果来自 CVS2 的DepartmentDivision列的值与来自 CSV1 的 MainGroup 列的值匹配,则将匹配的值保留在结果中。

是的,我可以使用Compare-Objectcmdlet,但很难想象我需要比较值并获得结果的循环。此外,MainGroup列可以有几个值除以逗号,这就是为什么我必须比较列并保留与MainGroup列匹配或保留结果原始值的列,如果DepartmentDivision为空。

CSV1 示例:

姓名 用户名 主组
戴夫戴维森 戴夫 NCR
雨果·洛森 雨果 军团
海乌戈 CBA
伦达尔回声 伦达尔 NCR,CBA

CVS2 示例:

姓名 用户名 部门 分配
戴夫戴维森 戴夫 NCR
雨果·洛森 雨果 军团 NCR
海乌戈
伦达尔回声 伦达尔 军团

标签: powershellcsvcompare

解决方案


毫无疑问,有一种更简洁、更好的方法可以用更少的代码执行此操作 - 但是我通常发现创建一个类来填充 CSV 比较的结果更容易,因为这样可以更轻松地获得 CSV 的输出。

这可以简化,但希望这将有助于解释循环/流程。将其复制到文件中(例如;Comapre-Csv.ps1),然后像这样运行它;

.\Compare-Csv.ps1 -SourceCsv .\csv_1.csv -ComparisonCsv .\csv_2.csv -ExportPath .\result.csv

脚本:

param (
    [string]
    $SourceCsv,
    [string]
    $ComparisonCsv,
    [string]
    $ExportPath
)
# Import both CSV's
$source = Import-Csv $SourceCsv
$comparison = Import-Csv $ComparisonCsv

# Create a class/array for easier CSV export
class ResultLine {
    [string]$Name
    [string]$UserName
    [string]$MainGroup
}
[ResultLine[]]$results = @()

foreach($sourceRow in $source) {
    # Find row in the comparison CSV by filtering to UserName
    $comparisonRow = $comparison | Where-Object -Property UserName -eq $sourceRow.UserName
    if($comparisonRow) {
        Write-Host "Comparing [$($sourceRow.UserName)] to [$($comparisonRow.UserName)]"
        
        # default to MainGroup - will be be overwritten if found in comparison
        [string]$mainGroup = $sourceRow.MainGroup

        # Check the department/division values from the comaprison row
        if(($comparisonRow.Department) -and ($comparisonRow.Division)) {
            # If the department & division are the same, just use the department
            if($comparisonRow.Department -eq $comparisonRow.Division) {
                $mainGroup = $comparisonRow.Department
            } else {
                $mainGroup = "$($comparisonRow.Department),$($comparisonRow.Division)"
            }
        }
        elseif($comparisonRow.Department) {
            $mainGroup = $comparisonRow.Department
        }
        elseif($comparisonRow.Division) {
            $mainGroup = $comparisonRow.Division
        }

        # Store the result
        $results += [ResultLine]@{
            Name = $sourceRow.Name
            UserName = $sourceRow.UserName
            MainGroup = $mainGroup
        }
    }
    else {
        Write-Host "[$($sourceRow.UserName)] not found in [$ComparisonCsv]" -ForegroundColor Yellow
    }
}

# Export CSV
$results | Export-Csv -Path $ExportPath -NoTypeInformation

就像我说的,有更短、更清洁的方法——但希望这会有所帮助。请记住,如果UserName 不在源中,但目标中,则此脚本将无法处理。


推荐阅读