Home >
Windows にまつわる e.t.c.
PowerShell で N:N キー マッチングする
古典的な N:N キー マッチングを PowerShell で書く機会があったので、汎用化してみました。
(もう少しすっきり書けそうですが、いろいろいじるとテストが面倒なのでほぼそのまま w)
機能
・2つオブジェクト(Master/Tran)の任意プロパティをマッチング キーにしてキー マッチングします。
・Master だけのオブジェクト、Tran
だけのオブジェクト、マッチしたオブジェクトを返します。
・同一キーが複数存在している場合は、最初に処理をしたオブジェクトのみ対象にします(以降のキー重複オブジェクトは読み飛ばし)
使い方
以下のマッチング キー ハンドリング部分を修正し、コードを組み込んでください。
【MasterKeyProperty】
【TranKeyProperty】
キーが複数ある場合は、 sort は複数キー指定ができますの。キー セットはよしなに修正してください。
コード
# マッチング状態定数
$LC_Mode_Matchi = 0
$LC_Mode_MasterOnly = 1
$LC_Mode_TranOnly = 2
$LC_Mode_Oter = 9
#######################################################
# マスター Key セット
#######################################################
function SetMasterKey($MasterObjects){
return $MasterObjects.【MasterKeyProperty】
}
#######################################################
# トランキー Key セット
#######################################################
function SetTranKey($TranObjects){
return $TranObjects.【TranKeyProperty】
}
#######################################################
# マッチング 状態判定
#######################################################
function GetMatchingStatus( $MasterKey, $Master_EOD, $TranKey, $Tran_EOD ){
$ReturnMode = $LC_Mode_Oter
# マスター終了
if( $Master_EOD -eq $true ){
$ReturnMode = $LC_Mode_TranOnly
}
# トラン終了
elseif( $Tran_EOD -eq $true ){
$ReturnMode = $LC_Mode_MasterOnly
}
# キーが等しい
elseif( $MasterKey -eq $TranKey ){
$ReturnMode = $LC_Mode_Matchi
}
# マスターが小さい
elseif( $MasterKey -lt $TranKey ){
$ReturnMode = $LC_Mode_MasterOnly
}
# トランが小さい
elseif( $TranKey -lt $MasterKey ){
$ReturnMode = $LC_Mode_TranOnly
}
return $ReturnMode
}
#######################################################
# マッチング処理
#######################################################
function Matching([array]$MasterObjects, [array]$TranObjects){
### Master前処理
# Master 終わったフラグ
$Master_EOD = $false
# Sort
[array]$MasterData = $MasterObjects | Sort-Object 【MasterKeyProperty】
# Max 件数
$Master_Max = $MasterData.Count
# Key 初期セットset
$Master_Index = 0
if( $MasterData.Count -ne 0 ){
$MasterKey = SetMasterKey $MasterData[$Master_Index]
}
else{
$Master_EOD = $true
}
### Tran 前処理
# Tran 終わったフラグ
$Tran_EOD = $false
# Sort
[array]$TranData = $TranObjects | Sort-Object 【TranKeyProperty】
# Max 件数
$Tran_Max = $TranData.Count
# Key 初期セットset
$Tran_Index = 0
if( $TranData.Count -ne 0 ){
$TranKey = SetTranKey $TranData[$Tran_Index]
}
else{
$Tran_EOD = $true
}
# Master Only Data
$MasterOnlyData = @()
# Tran Only Data
$TranOnlyData = @()
# MatchData
$MatchData = @()
# 件数カウンター
$MatchCount = 0
$MasterOnlyCount = 0
$TranOnlyCount = 0
# マッチング
while( -not (($Master_EOD -eq $true) -and ($Tran_EOD -eq $true)) ){
# マッチング 状態取得
$MatchingStatus = GetMatchingStatus $MasterKey $Master_EOD $TranKey $Tran_EOD
# Master Only
if( $MatchingStatus -eq $LC_Mode_MasterOnly ){
# Master データ収集
$AddData = $MasterData[$Master_Index]
$MasterOnlyData += $AddData
# Master Key Set
$NowKey = $MasterKey
# キーが割れるまで読み飛ばす
do{
# 件数カウント
$MasterOnlyCount++
$Master_Index++
if( $Master_Index -ge $Master_Max ){
$Master_EOD = $true
$NewKey = $null
}
else{
$MasterKey = SetMasterKey $MasterData[$Master_Index]
$NewKey = $MasterKey
}
}while( $NowKey -eq $NewKey )
}
# Tran Only
elseif( $MatchingStatus -eq $LC_Mode_TranOnly ){
# Tran データ収集
$AddData = $TranData[$Tran_Index]
$TranOnlyData += $AddData
# Tran Key Set
$NowKey = $TranKey
# キーが割れるまで読み飛ばす
do{
# 件数カウント
$TranOnlyCount++
$Tran_Index++
if( $Tran_Index -ge $Tran_Max ){
$Tran_EOD = $true
$NewKey = $null
}
else{
$TranKey = SetTranKey $TranData[$Tran_Index]
$NewKey = $TranKey
}
}while( $NowKey -eq $NewKey )
}
# マッチ
else{
# Match データ収集
# (Master をセット。必要に応じて Tran セットに書き換える)
$AddData = $MasterData[$Master_Index]
$MatchData += $AddData
# Master Key Set
$NowKey = $MasterKey
# キーが割れるまで読み飛ばす
do{
# 件数カウント
$MatchCount++
$Master_Index++
if( $Master_Index -ge $Master_Max ){
$Master_EOD = $true
$NewKey = $null
}
else{
$MasterKey = SetMasterKey $MasterData[$Master_Index]
$NewKey = $MasterKey
}
}while( $NowKey -eq $NewKey )
# Tran Key Set
$NowKey = $TranKey
do{ # キーが割れるまで読み飛ばす
$Tran_Index++
if( $Tran_Index -ge $Tran_Max ){
$Tran_EOD = $true
$NewKey = $null
}
else{
$TranKey = SetTranKey $TranData[$Tran_Index]
$NewKey = $TranKey
}
}while( $NowKey -eq $NewKey )
}
}
# 戻り値セット
$ReturnData = New-Object PSObject | Select-Object`
MasterOnlyData, # マスターオンリー
MatchData, # マッチ
TranOnlyData # トランオンリー
$ReturnData.MasterOnlyData = $MasterOnlyData
$ReturnData.MatchData = $MatchData
$ReturnData.TranOnlyData = $TranOnlyData
return $ReturnData
}
|
実装例
MatchingTest.ps1
### ここにコードコピペ
# マスタセット
$MasterData = Import-Csv "C:\temp\MatchTest\Master.csv"
# トランセット
$TranData = Import-Csv "C:\temp\MatchTest\Tran.csv"
# マッチング
$RetData = Matching $MasterData $TranData
# マッチング結果データ取り出し
$MasterOnlyData = $RetData.MasterOnlyData
$TranOnlyData = $RetData.TranOnlyData
$MatchData = $RetData.MatchData
# マッチング結果表示
echo "MasterOnly : "
$MasterOnlyData | ft *
echo ""
echo "TranOnly : "
$TranOnlyData | ft *
echo ""
echo "Match : "
$MatchData | ft *
|
参考情報
PowerShell の Sort-Object Tips
http://www.vwnet.jp/windows/PowerShell/2017032901/Sort-Object_Tips.htm
Copyright © MURA
All rights reserved.