2개의 어레이를 비교하여 일반적이지 않은 값을 취득하다
두 어레이의 내용을 비교하고 powershell을 사용하여 공통적이지 않은 값을 얻을 수 있는 작은 논리를 원했습니다.
예를 들면
$a1=@(1,2,3,4,5)
$b1=@(1,2,3,4,5,6)
$c, 즉 출력은 "의 값을 얻을 수 있습니다.6
두 어레이 간의 일반적인 가치를 나타내는 출력입니다.
누가 나 좀 도와줄래! 고마워!
PS > $c = Compare-Object -ReferenceObject (1..5) -DifferenceObject (1..6) -PassThru
PS > $c
6
$a = 1..5
$b = 4..8
$Yellow = $a | Where {$b -NotContains $_}
$Yellow
의 모든 항목이 포함되어 있습니다.$a
안에 있는 것들만 빼고$b
:
PS C:\> $Yellow
1
2
3
$Blue = $b | Where {$a -NotContains $_}
$Blue
의 모든 항목이 포함되어 있습니다.$b
안에 있는 것들만 빼고$a
:
PS C:\> $Blue
6
7
8
$Green = $a | Where {$b -Contains $_}
문제 없습니다만, 어쨌든, 양쪽 모두에 포함되는 아이템이 포함되어 있습니다.$a
그리고.$b
.
PS C:\> $Green
4
5
주의:Where
의 에일리어스입니다.Where-Object
. 에일리어스로 인해 발생할 수 있는 문제가 발생하여 스크립트를 유지보수가 어려워질 수 있습니다.
2019년 10월 12일 부록
@xtreampb 및 @mklement0에 의해 코멘트된 바와 같이 질문의 예에서는 표시되지 않지만 질문에 포함된 태스크('공통하지 않은 값')는 두 입력 세트 간의 대칭 차이입니다(노란색과 파란색의 결합).
유니언
의 대칭적 차이$a
그리고.$b
문자 그대로의 결합이라고 정의할 수 있다$Yellow
그리고.$Blue
:
$NotGreen = $Yellow + $Blue
다음과 같이 기술되어 있습니다.
$NotGreen = ($a | Where {$b -NotContains $_}) + ($b | Where {$a -NotContains $_})
성능
아시다시피 이 구문에는 상당히 많은 (용장) 루프가 있습니다.목록의 모든 항목$a
반복(사용)Where
)에서 목록 항목까지$b
(사용)-NotContains
) 및 비자(visa)도 마찬가지입니다.유감스럽게도 양측의 결과를 예측하기 어렵기 때문에 중복을 피하기 어렵다.해시 테이블은 보통 다중 루프의 성능을 향상시키는 데 적합한 솔루션입니다.이를 위해 저는 다음과 같은 질문을 재정의하고 싶습니다.컬렉션 합계에 한 번 표시되는 값을 가져옵니다().$a + $b
$Count = @{}
$a + $b | ForEach-Object {$Count[$_] += 1}
$Count.Keys | Where-Object {$Count[$_] -eq 1}
를 사용하여ForEach
스테이트먼트 대신ForEach-Object
cmdlet 및Where
대신 메서드Where-Object
성능을 2.5배 높일 수 있습니다.
$Count = @{}
ForEach ($Item in $a + $b) {$Count[$Item] += 1}
$Count.Keys.Where({$Count[$_] -eq 1})
LINQ
단, Language Integrated Query(LINQ)는 어떤 네이티브 PowerShell 및 네이티브를 능가합니다.넷 메서드(LINQ를 탑재한 고성능 PowerShell 및 mklement0의 "다음 네스트된 포어치 루프는 PowerShell에서 심플화할 수 있습니까?"에 대한 답변도 참조하십시오.
LINQ를 사용하려면 어레이 유형을 명시적으로 정의해야 합니다.
[Int[]]$a = 1..5
[Int[]]$b = 4..8
또,[Linq.Enumerable]::
연산자:
$Yellow = [Int[]][Linq.Enumerable]::Except($a, $b)
$Blue = [Int[]][Linq.Enumerable]::Except($b, $a)
$Green = [Int[]][Linq.Enumerable]::Intersect($a, $b)
$NotGreen = [Int[]]([Linq.Enumerable]::Except($a, $b) + [Linq.Enumerable]::Except($b, $a))
대칭 제외와 함께
(2022-05-02 추가)
클래스의 메서드를 사용하고 있는 대칭의 차이를 취득하는 다른 방법도 있습니다.상세한 것에 대하여는, 다음의 2개의 매우 큰 리스트로 무엇이 다른지를 참조해 주세요.
$a = [System.Collections.Generic.HashSet[int]](1..5)
$b = [System.Collections.Generic.HashSet[int]](4..8)
$a.SymmetricExceptWith($b)
$NotGreen = $a # note that the result will be stored back in $a
벤치마크
(2022-05-02 업데이트, @Santiago 벤치마크 스크립트 개선 감사합니다)
벤치마크 결과는 컬렉션의 크기와 실제로 공유되는 항목의 수에 따라 크게 달라집니다.또한 LINQ와 마찬가지로 지연된 평가(지연된 실행이라고도 함)를 사용하는 방법에 대한 결론을 도출하는 경고도 있습니다.SymmetricExceptWith
결과@($a)[0]
)는 식을 평가하기 위해 수행되어야 할 작업을 정의하는 것 외에 아직 수행되지 않았기 때문에 예상보다 오랜 시간이 걸릴 수 있습니다.다음 항목도 참조하십시오.배열 속성에서 고유 인덱스 항목을 가져오는 가장 빠른 방법
어쨌든, 「평균」으로서 각 컬렉션의 절반은 다른 컬렉션과 공유되고 있는 것을 상정하고 있습니다.
Test TotalMilliseconds
---- -----------------
Compare-Object 118.5942
Where-Object 275.6602
ForEach-Object 52.8875
foreach 25.7626
Linq 14.2044
SymmetricExce… 7.6329
성능을 제대로 비교하려면 새로운 PowerShell 세션을 시작하는 등의 방법으로 캐시를 지워야 합니다.
[Int[]]$arrA = 1..1000
[Int[]]$arrB = 500..1500
Measure-Command {&{
$a = $arrA
$b = $arrB
Compare-Object -ReferenceObject $a -DifferenceObject $b -PassThru
}} |Select-Object @{N='Test';E={'Compare-Object'}}, TotalMilliseconds
Measure-Command {&{
$a = $arrA
$b = $arrB
($a | Where {$b -NotContains $_}), ($b | Where {$a -NotContains $_})
}} |Select-Object @{N='Test';E={'Where-Object'}}, TotalMilliseconds
Measure-Command {&{
$a = $arrA
$b = $arrB
$Count = @{}
$a + $b | ForEach-Object {$Count[$_] += 1}
$Count.Keys | Where-Object {$Count[$_] -eq 1}
}} |Select-Object @{N='Test';E={'ForEach-Object'}}, TotalMilliseconds
Measure-Command {&{
$a = $arrA
$b = $arrB
$Count = @{}
ForEach ($Item in $a + $b) {$Count[$Item] += 1}
$Count.Keys.Where({$Count[$_] -eq 1}) # => should be foreach($key in $Count.Keys) {if($Count[$key] -eq 1) { $key }} for fairness
}} |Select-Object @{N='Test';E={'foreach'}}, TotalMilliseconds
Measure-Command {&{
$a = $arrA
$b = $arrB
[Int[]]([Linq.Enumerable]::Except($a, $b) + [Linq.Enumerable]::Except($b, $a))
}} |Select-Object @{N='Test';E={'Linq'}}, TotalMilliseconds
Measure-Command {&{
$a = $arrA
$b = $arrB
($r = [System.Collections.Generic.HashSet[int]]::new($a)).SymmetricExceptWith($b)
}} |Select-Object @{N='Test';E={'SymmetricExceptWith'}}, TotalMilliseconds
Compare-Object
Compare-Object $a1 $b1 | ForEach-Object { $_.InputObject }
오브젝트가 어디에 속해 있는지 알고 싶다면 SideIndicator를 참조하십시오.
$a1=@(1,2,3,4,5,8)
$b1=@(1,2,3,4,5,6)
Compare-Object $a1 $b1
시험:
$a1=@(1,2,3,4,5)
$b1=@(1,2,3,4,5,6)
(Compare-Object $a1 $b1).InputObject
또는 다음을 사용할 수 있습니다.
(Compare-Object $b1 $a1).InputObject
순서는 중요하지 않아요.
어레이를 먼저 정렬하지 않으면 결과는 도움이 되지 않습니다.배열을 정렬하려면 Sort-Object를 통해 배열을 실행합니다.
$x = @(5,1,4,2,3)
$y = @(2,4,6,1,3,5)
Compare-Object -ReferenceObject ($x | Sort-Object) -DifferenceObject ($y | Sort-Object)
간단한 해시 테이블을 사용하면 도움이 될 것입니다.
$a1=@(1,2,3,4,5) $b1=@(1,2,3,4,5,6)
$hash= @{}
#storing elements of $a1 in hash
foreach ($i in $a1)
{$hash.Add($i, "present")}
#define blank array $c
$c = @()
#adding uncommon ones in second array to $c and removing common ones from hash
foreach($j in $b1)
{
if(!$hash.ContainsKey($j)){$c = $c+$j}
else {hash.Remove($j)}
}
#now hash is left with uncommon ones in first array, so add them to $c
foreach($k in $hash.keys)
{
$c = $c + $k
}
언급URL : https://stackoverflow.com/questions/6368386/comparing-two-arrays-get-the-values-which-are-not-common
'programing' 카테고리의 다른 글
WPF 익스팬더 헤더의 스타일링 방법 (0) | 2023.04.16 |
---|---|
데이터베이스 및 테이블을 생성하는 SQL 스크립트 생성 (0) | 2023.04.11 |
Silverlight와 유사한 WPF에서의 검증 오류 스타일 (0) | 2023.04.11 |
파이프의 다른 쪽 끝에는 프로세스가 없습니다(SQL Server 2012). (0) | 2023.04.11 |
어레이를 bash 매개 변수로 전달 (0) | 2023.04.11 |