পাওয়ারশেলে দুটি বহুমাত্রিক অ্যারে তুলনা করা হচ্ছে


3

আমি পাওয়ারশেলে দুটি বহুমাত্রিক অ্যারে তুলনা করার চেষ্টা করছি। প্রতিটি অ্যারে অনেক হাজার উপাদান রয়েছে - একটি ছোট উদাহরণ অনুসরণ করে। একটি অ্যারেতে আমার কাছে রয়েছে:

$arrOne
Username                        LocalOffice
john.doe@domain.com             US-California
need.help@domain.com            IT-Naples
another.example@domain.com      TR-Istanbul
(etc...)

অন্যান্য অ্যারেতে, আমার কাছে রয়েছে:

$arrTwo
Username                        Location
john.doe@domain.com             US
need.help@domain.com            US
another.example@domain.com      TR
(etc...)

আমি কি করতে প্রয়োজন তুলনা হয় LocalOffice প্রতিটি সঙ্গে যুক্ত ব্যবহারকারীর নাম থেকে $ Arrone প্রথম দুই অক্ষর অবস্থান মিলে ব্যবহার ব্যবহারকারীর নাম মধ্যে $ arrTwo (যদি থাকে তাহলে)। তাহলে LocalOffice এবং অবস্থান মিলছে না তারপর কিছু ব্যবস্থাগুলি নিতে। আমার কোডের নমুনাটি নিম্নরূপ:

$arrOne | ForEach-Object {
    $strOneName = $_.Username
    If ($_.LocalOffice.Length -ge 2)
        {
        $strOneLocalOffice = $_.LocalOffice.substring(0,2)
        }
    Else
        {
        $strOneLocalOffice = "US"
        }
    $arrTwo | ForEach-Object {
        If ($_.Username -eq $strOneName -eq $True)
            {
            If ($_.Location -eq $strOneLocalOffice -ne $True)
                {
                ## Take action here if they don't match
                write-host $_.Username
                }
            }
    }
}

স্ট্যান্ডার্ড নেস্টেড ফরইচ (উপরে) দিয়ে, এই অ্যারেগুলি প্রক্রিয়া করতে কিছুটা সময় লাগে কারণ প্রতিটি অ্যারে বড় হয় (এবং এটি প্রতি 30 মিনিটে চলে এমন স্ক্রিপ্টের অংশ হবে) এবং সময় সংবেদনশীল। আশা করি আমার উত্তরটি খুঁজে পেতে আমার উপরোক্ত সম্পর্কে কয়েকটি প্রশ্ন রয়েছে:

1)  Is there some other (quicker) method to get the desired results?

2)  Do I have to use ForEach and loop through arrTwo until I find the matching
Username from arrOne or is there some other quicker method to jump right to the
matching Username in arrTwo?

3)  Is there a way to quickly merge (join) these two arrays together so then I
can ForEach once through a single array and just compare individual objects
from the same element?

ধন্যবাদ

আপডেট :

আমরা আমাদের স্থানীয় সক্রিয় ডিরেক্টরি এবং এমএসএল (মাইক্রোসফ্ট অনলাইন - অফিস 365) অবজেক্টগুলি পরিচালনা করতে সহায়তা করতে এই স্ক্রিপ্টটি ব্যবহার করি। আমরা Office 365 এর সাথে আমাদের এডি সিঙ্ক রাখতে ডিআরসিঙ্ক ব্যবহার করছি read পাঠযোগ্যতার জন্য উপরের উদাহরণগুলিতে নাম পরিবর্তন করা হলেও অ্যারে ডেটা সংগ্রহ করার জন্য এগুলি ব্যবহৃত প্রাথমিক আদেশগুলি:

[array]$arrOne = @(Get-ADObject -Filter {(objectClass -eq "User") -And (objectCategory -eq "Person")} -SearchBase “OU=Test,DC=domain,DC=com” -Properties UserPrincipalName,physicalDeliveryOfficeName) | Select-Object UserPrincipalName, physicalDeliveryOfficeName

[array]$arrTwo = @(Get-MsolUser -Synchronized -All) | Where-Object {$_.isLicensed -eq "True"} | Select-Object UserPrincipalName, UsageLocation

অ্যারেগুলি বিভিন্ন আকারের হয় (আর্টওনটি আক্ষরিকভাবে আরনের আকারের 10 গুণ বেশি)। এ্যারন থেকে কোনও বস্তু আর্ট টুতে উপস্থিত থাকবে এমন কোনও গ্যারান্টি নেই।

আমার মূল পোস্টিং (বিশেষত দ্বিতীয় লুপটি থেকে বেরিয়ে আসার জন্য BREAK ব্যবহার করে) এই সমস্যাটি সমাধান করার জন্য আমি আরও কয়েকটি বিষয় চেষ্টা করেছি। আসল পোস্টের পরে, আমি বুঝতে পেরেছিলাম যে কোনও ম্যাচ পাওয়া গেলে আমি দ্বিতীয় ফোয়ার-অবজেক্ট লুপটি থেকে "ব্রেক" করতে পারলে আমি সেরা পারফরম্যান্সের উন্নতি পেতে পারি। একটি জিনিস যা জিনিসগুলিকে মন্থর করে দিচ্ছে তা হ'ল পাওয়ারশেল একটি মিল খুঁজে পাওয়ার পরেও আর্ট টুতে লুপিং চালিয়ে যায়। একটি ম্যাচ সন্ধানের পরে আমি বিরতি যুক্ত করার চেষ্টা করেছি তবে আর্ট টু লুপটি বের হয়ে আরোন সংগ্রহে পরবর্তী বস্তুতে ফিরে আসতে পারছি না। এটি সম্পূর্ণ স্ক্রিপ্টটি ভঙ্গ করে (শেষ করে)।

    $arrTwo | ForEach-Object {
        If ($_.Username -eq $strOneName -eq $True)
            {
            If ($_.Location -eq $strOneLocalOffice -ne $True)
                {
                ## Take action here if they don't match
                write-host $_.Username
                }
            Break
            }
    }

আমি বিরতি, বিরতি / চালিয়ে যাওয়া, ব্রেক / লেবেল, ফোরচ-অবজেক্টের পরিবর্তে ফোরচ ব্যবহার করে / করার সময় এবং আরও কিছু চেষ্টা করেছি। এখনও ভাগ্য নেই।

একটি অতিরিক্ত প্রশ্ন:

4)  Can break be used to exit a ForEach-Object loop and return it to the “parent”
ForEach-Object?

আবার ধন্যবাদ


1
অ্যারে কিভাবে তৈরি হয়? ব্যবহারকারীর নাম ক্ষেত্রটি কি অনন্য?
ইবিগ্রিন

এছাড়াও, অ্যারেগুলি কি একই আকারের?
zdan

@EBGreen - উপরে আপডেট তথ্য দেখুন।
এসটিজিডিবি

@ জদান - দুঃখিত, তারা একই আকার নয়। $ এআরন $ এআরআর থেকে অনেক ছোট
STGdb

উত্তর:


2

আপনার সহায়তার জন্য সবাইকে ধন্যবাদ - তারা আমার সমস্যার সমাধান করার জন্য একটি সমাধান খুঁজতে এবং ব্রেক / সঠিকভাবে কাজ চালিয়ে যাওয়ার জন্য আমাকে নেতৃত্ব দিতে সহায়তা করেছিল । এখন পারফরম্যান্স তুলনামূলক বেশি। আমাকে ফোরইচ-অবজেক্ট থেকে ফরইচে অভ্যন্তরীণ লুপ (r আরআরটো) পরিবর্তন করতে হয়েছিল। এটি লুপটি শুরু করার পদ্ধতিটি পরিবর্তিত করে iated

$arrOne | ForEach-Object {
    If ($_.LocalOffice.Length -ge 2)
        {
        $strOneOffice = $_.LocalOffice.substring(0,2)
        }
    Else
        {
        $strOneOffice = "US"
        }
    ForEach ($objTwo in $arrTwo) {
    If ($objTwo.Username -eq $_.Username)
        {
        If ($objTwo.UsageLocation -eq $strOneOffice -ne $True)
            {
            ## Take action here if they don't match
            write-host $_.Username "needs to be updated"
            Break
            }
        Else
            {
            ## Nothing to update here because they already match
            write-host $_.Username "does not need to be updated"
            Continue
            }
        }
    }
}

1

আমি সন্দেহ করি যে আপনার ডেটা একটি অ্যাক্টিভ ডিরেক্টরি থেকে আসছে। একজন "আসল" প্রোগ্রামারটির আরও ভাল পদ্ধতির হতে পারে, তবে আমি মনে করি আপনি প্রথমে আপনার অ্যারে বাছাই করে কর্মক্ষমতা উন্নত করতে পারেন, তারপরে এটির থেকে আপনার মানটি আর্ট টু ব্যবহারের মধ্যে অন্তর্ভুক্ত কিনা তা পরীক্ষা করে -contains। ফলাফলের উপর নির্ভর করে আপনি আরআরটো থেকে প্রকৃত মানগুলি পরীক্ষা করতে পারেন। এই নিবন্ধটি পরীক্ষা করে দেখুন , এটি বাছাই করা পারফরম্যান্স সমস্যার সমাধান করে addresses এছাড়াও কটাক্ষপাত করা তুলনা-বস্তুর commandlet আপনার অ্যারে তুলনা।


হ্যাঁ, অ্যারেগুলির মধ্যে একটি এডি থেকে আসছে। অন্যটি অফিস 365 (এমএসএল) এর। আমি বুঝতে পেরেছিলাম যে আমার সেরা পারফরম্যান্সের লাভটি ম্যাচটি পাওয়া গেলে আর্ট টুতে লুপিং বন্ধ করা হবে তবে ম্যাচটি সন্ধানের পরে আমি এটি আরেওনে ফিরতে পারি না। আমি তুলনা ব্যবহার করার চেষ্টা করেছি কিন্তু দুর্ভাগ্যক্রমে এটি কোনও উপকারে আসেনি। যদিও ভাল ধারণা - আপনাকে ধন্যবাদ।
এসটিজিডিবি

0

আপনি যা এড়াতে চান তা হ'ল প্রথম প্রতিটি সারির জন্য দ্বিতীয় অ্যারেটি অনুসন্ধান করা। সেরা উপায়টি 2 অ্যারের প্রকৃতির উপর নির্ভর করবে (মন্তব্যে জিজ্ঞাসিত প্রশ্নগুলি দেখুন)। ধরে নেওয়া যে অ্যারেগুলি প্রায় একই আকারের, আপনি যা করবেন তা একই সাথে উভয় অ্যারে লুপ করা হবে (একটি সূচক ব্যবহার করে) এবং ফলাফলগুলি সংরক্ষণ করে এমন এক ধরণের টেবিল তৈরি করুন। তারপরে আপনার ফলাফলগুলি পরীক্ষা করতে সেই টেবিলটি দিয়ে লুপ করুন (নীচের উদাহরণ দেখুন)। এখন আমি এটি স্পষ্টতার জন্য 2 টি লুপে রেখেছি, তবে যখনই কোনও হ্যাশটেবলের প্রবেশ সম্পূর্ণ হয়েছিল এবং ততক্ষণে আপনি প্রথম লুপটিতে একটি চেক যোগ করতে পারেন।

$ht = @{} # to store the results
#note this code could be simpler if the arrays are sorted  or the same length
for($i=0; $i -lt [Math]::Max($arrOne.Length,$arrTwo.Length); $i++){
    if($i -lt $arrOne.Length)
    {
        if($ht[$arrOne[$i].UserName])
        {
            #just modify the null value.
            $ht[$arrOne[$i].UserName].LocalOffice = $arrOne[$i].LocalOffice;
        }
        else
        {
            #create a new entry
            $ht[$arrOne[$i].UserName] = @{"LocalOffice"=$arrOne[$i].LocalOffice; "Location"=$null;}
        }
    }
    if($i -lt $arrTwo.Length)
    {
        if($ht[$arrTwo[$i].UserName])
        {
            $ht[$arrTwo[$i].UserName].Location = $arrTwo[$i].Location;
        }
        else
        {
            #create a new entry
            $ht[$arrTwo[$i].UserName] = @{"Location"=$arrTwo[$i].Location; "LocalOffice"=$null;}
        }
    }
 }

 # now loop through the resulting table
 $ht.Keys | foreach {
    if($ht[$_].LocalOffice -and $ht[$_].Location)
    {
        if($ht[$_].LocalOffice.Substring(0,2) -ne $ht[$_].Location)
        {
            "Problem for $_";
        }
    }
}

কোডের জন্য আপনাকে ধন্যবাদ। দুর্ভাগ্যক্রমে অ্যারেগুলি একই আকার নয়। $ arrOne $ artwo এর চেয়ে অনেক ছোট (অনেক ছোট)। আমি উপরের মূল পোস্টে কিছু নোট যুক্ত করেছি। আমি মনে করি যে আমি বুঝতে পেরেছি যে আমার সেরা পারফরম্যান্সের লাভটি কোনও মিল পাওয়া গেলে ২ য় লুপ থেকে বেরিয়ে আসা এবং প্রথম লুপের পরবর্তী বস্তুতে ফিরে আসা। তবে আমি এটি সঠিকভাবে কাজ করতে পারিনি। আমি এখনও হ্যাশ টেবিলের কাজ পাচ্ছি - কাজ চলছে progress
এসটিজিডিবি

0

আমি জানতে চাইছি কেন ডেভিডপস্টিল আমার উত্তর সরিয়ে দিয়েছে? আমি সরাসরি তাকে বার্তা দেওয়ার কোনও উপায় দেখি না, এর জন্য দুঃখিত। আমি কোড এবং এর সাথে কিছু মন্তব্য সহ উত্তর দিয়েছি। এটি একটি অনন্য উত্তর ছিল, যেমন কোনও সদৃশ নয় এবং সম্ভবত পোস্ট করা অন্যান্য পদ্ধতির তুলনায় আরও দক্ষ efficient যদি এই পোস্টটি 4 বছরের পুরানো কারণ হয় তবে পুরানো পোস্টগুলিতে মন্তব্য না করার জন্য এবং সহায়ক হতে আপনার সহায়তা কেন্দ্র আপডেট করুন। গুগলে কোনও অনুরূপ কিছু সন্ধান করার জন্য পোস্টটি পেরিয়ে এসেছি, নিজেই উত্তর দিয়ে শেষ করেছি। উত্তর আবার নীচে।


আমি জানি এটি 4 বছর বয়সী, তবে আমি নিশ্চিত যে এটি সম্ভবত এখনও ঘটছে। আমি ভেবেছিলাম আমি হ্যাশ টেবিলগুলি ব্যবহার করা এই ক্ষেত্রে সুবিধাজনক না হলে আমি জিজ্ঞাসা করব যাতে কোনও কিছুরই ম্যাচ আশা করে প্রত্যেকে পুনরাবৃত্তি করার পরিবর্তে আপনি সরাসরি কোনও নির্দিষ্ট ফলাফলের জন্য প্রশ্ন করতে পারেন।

আমি স্বীকার করি, আপনার কোডটি আপনার $ ArrOne এবং $ ArrToo উদাহরণ হিসাবে চূড়ান্ত কোডের পরামর্শ অনুসারে একই বৈশিষ্ট্যগুলি ব্যবহার করে না বলে আমার সমস্যা হচ্ছে। অর্থাত্ ব্যবহারকারীর নাম বনাম ব্যবহারকারীর প্রিন্টিকালনাম, সুতরাং কোডটি সহ্য করুন এবং সেই অনুযায়ী আপডেট করুন।

যেভাবে আমি এর কাছে পৌঁছেছি তা হল আমি 2 টি অ্যারে সংগ্রহ করব gather আপনি জানেন যে একটি অ্যারে আপনি আপডেট করছেন (অফিস 365) এবং অন্য অ্যারে (r আরোন) আপনি নিজের উত্স / মাস্টার ডেটা হিসাবে ব্যবহার করবেন। সুতরাং আপনি প্রতিটি অ্যারের জন্য একটি হ্যাশ টেবিল তৈরি করতে চান এবং আপনার ক্ষুদ্রতর অ্যারে ব্যবহার করবেন, যেমন r আরআরটো দুইটি আপনি ফরইচ করছেন এমন হিসাবে। কেবল সেই মানগুলিই আমাদের মেলে বা না পাওয়ার বিষয়ে যত্নশীল।

আমি যখন 2 হ্যাশটবগুলি তৈরি করি তখন আমি ব্যবহারকারীর প্রিন্সিপাল নামটি কী হিসাবে ব্যবহার করি। অর্থাৎ ইউজার@company.com $ হাশ ['User@company.com '] হিসাবে পুনরুদ্ধার করা হবে এবং আপনি যদি লোকালঅফিস সম্পত্তিটি চান, এটি হবে $ হ্যাশ [' ব্যবহারকারীর_কম্পনি.কম '] Local লোকালঅফিস তাই আমাদের যা করতে হবে প্রথম হ্যাশ টেবিলের সাথে মানগুলির তুলনা করা এবং তদনুসারে আপডেট করার জন্য 2 হ্যাশ টেবিলের ছোটগুলির জন্য সমস্ত কিগুলির মধ্য দিয়ে লুপ হয়।

[array]$arrOne = @(Get-ADObject -Filter {(objectClass -eq "User") -And (objectCategory -eq "Person")} -SearchBase “OU=Test,DC=domain,DC=com” -Properties UserPrincipalName,physicalDeliveryOfficeName) | Select-Object UserPrincipalName, physicalDeliveryOfficeName

[array]$arrTwo = @(Get-MsolUser -Synchronized -All) | Where-Object {$_.isLicensed -eq "True"} | Select-Object UserPrincipalName, UsageLocation

#Create Hash for AD
$hash1 = $null
$hash1 = @{}
foreach ($u in $arrOne)
{
$hash1.add($u.UserPrincipalName,$u)
}

#Create Hash for Office365
$Hash2 = $null
$Hash2 = @{}
foreach ($u2 in $arrTwo)
{
$Hash2.add($u2.UserPrincipalName,$u2)
}


#Itterate through Office365 Keys (UserPrincipalNames).
$Hash2.keys | ForEach {
#Quick check to see if the Hash1 value exists (Is there a UPN in Hash1 that matches Hash2)
If ($hash1[$_])
  {  
    If ($Hash1[$_].LocalOffice.Length -ge 2)
        {
        $strOneOffice = $Hash1[$_].LocalOffice.substring(0,2)
        }
    Else
        {
        $strOneOffice = "US"
        }
  }
  else
{
#Continue as the UPN does not exist in $Hash1, which should be rare.  This should skip to the next entry in Hash2 and start over.
  Continue
  }
if (!($hash2[$_].UsageLocation  -eq $strOneOffice ))
        {
        ## Take action here if they don't match
        write-host "$($_) needs to be updated; OldValue: $($hash2[$_].UsageLocation); NewValue: $strOneOffice"
        }
    Else
        {
        ## Nothing to update here because they already match
        write-host "$($_) does not need to be updated"
        Continue
        }
}

(1)  সুপার ব্যবহারকারী সরাসরি বার্তাপ্রেরণ সমর্থন করে না। সঠিক জিনিসটি হ'ল আপনার উত্তরটি সম্পাদন করা (যা আপনি করেছেন) এবং তারপরে "পতাকা" ক্লিক করুন (পোস্টের নীচে, বাম দিকে, "মুছে ফেলা" কিংবদন্তীর উপরে)। (২) আমি ভেবেছিলাম যে আপনার পোস্টটি কোনও উত্তর নয় এবং প্রকৃতপক্ষে আমি এটিকে "উত্তর নয়" হিসাবে চিহ্নিত করেছি। দ্বিতীয় বাক্যটি "আমি ভেবেছিলাম আমি জিজ্ঞাসা করব ..." শুরু হয়, যা দেখে মনে হচ্ছে আপনি ফলো-আপ প্রশ্ন জিজ্ঞাসা করছেন। "আপনার কোড অনুসরণ করতে আমার সমস্যা হচ্ছে ..." দেখে মনে হচ্ছে আপনি স্পষ্টতা চাইছেন। … (চালিয়ে যাওয়া)
স্কট

(চালিয়ে যাওয়া) ... এটি মাঝে মাঝে উপযুক্ত হতে পারে তবে উত্তরে প্রশ্ন জিজ্ঞাসা করা এড়ানো ভাল। (3) দ্বিতীয় বর্ণনায়, আমি অনুমান করি যে দেখে মনে হচ্ছে আপনি কোনও উত্তর সরবরাহ করছেন। তবে আপনার কোডটি এত দীর্ঘ এবং এত প্রশস্ত (প্রথম লাইনটি 250 টির বেশি অক্ষরের বেশি) এটি পড়া শক্ত করে তোলে। আপনি লাইন ব্রেক inোকাতে পারেন? (4) বেমানান ইনডেন্টেশন শৈলী কোড পড়তেও শক্ত করে তোলে। (5) দুঃখিত আমি আপনার উত্তরটি পতাকাঙ্কিত করেছি। তবে উত্তরটি কীভাবে একটি উত্তরের মতো দেখানো যায় সে সম্পর্কে এখন আপনার কিছু পরিষ্কার নির্দেশ রয়েছে।
স্কট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.