Assign one variable based on a list of

This topic contains 2 replies, has 2 voices, and was last updated by  Tony 2 years, 8 months ago.

  • Author
    Posts
  • #23700

    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

    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

    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.