Assign one variable based on a list of

This topic contains 2 replies, has 2 voices, and was last updated by Profile photo of Tony Tony 1 year, 8 months ago.

  • Author
    Posts
  • #23700
    Profile photo of Tony
    Tony
    Participant

    Hello,
    I'm trying to include a function in a new user creation PowerShell script that will create a user's home folder and provide the necessary permissions based on information retrieved from a file called mappings.CSV. I can't seem to get this accomplished without using a bunch of static IF statements for each department code within the script itself.

    New users are initially read in to an array from a .CSV file at the start of the script. A ForEach loop creates users one at a time assigning all of the appropriate variables, creating the user mailbox, etc. A 4 digit code in that file read in to a variable called $userDeptCode and is used successfully elsewhere in my script. I need it to also create a home directory.

    In the first column of mappings.csv is a 4 digit department code. The second column is a UNC path for where the user's home directory should be created. I can read in the file file, I just can't seem to take the variable from $userDeptCode, match it to the code column of mappings.CSV, and assign the corresponding value in the 'share' column to $homedirectory. Sample CSV snippets are below:

    user.CSV
    username,deptcode
    asmith,1200
    bjohnson,1300
    bsmith,1300

    mappings.CSV
    code,share
    1200,\\server\shares$\marketing
    1300,\\server\shares$\accounting
    1400,\\server\shares$\finance

    So the end result: Based on the user who is read in from user.csv, compare his $deptcode value to the mappings array. Based on the match in the mappings array, assign the corresponding value for share.
    How can I accomplish this? I seem to consistently follow the wrong path. This is the last part I need, and it appears I've saved the best for last.
    I've already got the code written to create the home directory and assign the appropriate permissions for the user, I just can't get this one part working properly.

    Thanks in advance.

  • #23701
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    There are a few ways you could do this. I'll show the easiest to understand first, but the performance is unfortunately crap:

    
    $users = Import-Csv user.CSV
    $mappings = Import-Csv mappings.CSV
    
    foreach ($user in $users)
    {
        $share = $mappings | Where-Object { $_.code -eq $user.deptcode } | Select-Object -ExpandProperty Share
    }
    

    This is pretty straightforward to understand, using Where-Object and Select-Object -ExpandProperty. However, you're enumerating the $mappings array every time through the $users loop, which is essentially an O(N^2) algorithm. If you're dealing with a very small data set, you may not notice any slowness and it doesn't matter. If you've got a few hundred objects in each CSV, it starts to bog down a bit.

    You can speed this up greatly by enumerating your mappings array once and building a hashtable out of it, then doing the lookups in the hashtable from your users loop:

    $users = Import-Csv user.CSV
    $mappings = @{}
    
    Import-Csv mappings.CSV |
    ForEach-Object {
        $mappings[$_.Code] = $_.Share
    }
    
    foreach ($user in $users)
    {
        $share = $mappings[$user.deptcode]
    }
    
  • #23702
    Profile photo of Tony
    Tony
    Participant

    Thanks Dave. The datasets will always be small (less than 20 for mappings, less than 50 for users), but I'd much rather do it the second way. I was over-thinking the process and this helps. Thanks!

You must be logged in to reply to this topic.