1

I'm working with a script that should import my csv file, and randomly put 3 persons in a team, and make as many teams as there are players.

I can import my csv file, but i'm very lost on how to process from this point.

I know it's not alot, but I need help to get going.

$users = import-csv "C:\Users\Bruger\Dokumenter\Esport_liste.csv"
Write-Host $users

My CSV look like this: enter image description here

mklement0
  • 382,024
  • 64
  • 607
  • 775
Kunak
  • 37
  • 10
  • How does your csv looks like? – TobyU Nov 14 '18 at 10:04
  • @TobyU Please see my edit. – Kunak Nov 14 '18 at 10:08
  • A few things: 1. Don't use `Write-Host` with you import. The Function converts the imported-csv to an string, this is not what you want. 2. Take a look at `for`-loops: https://ss64.com/ps/for.html 3. For the random-part take a look at `Get-Random` 4. You csv is more like a text file than a real csv. If you are working with .csv files without headers, take a deeper look at how `import-csv` works. – Paxz Nov 14 '18 at 10:11
  • Possible duplicate of [Slice a PowerShell array into groups of smaller arrays](https://stackoverflow.com/questions/45948580/slice-a-powershell-array-into-groups-of-smaller-arrays) – henrycarteruk Nov 14 '18 at 10:13
  • @JamesC. Certainly related, but the linked question covers only _part_ of what is being asked here: the added element here is the desire to create fixed-size chunks with _randomly selected_ input elements. – mklement0 Nov 14 '18 at 16:28

2 Answers2

3

Here's one possible solution:

Say, you have a CSV like this:

Player
David
Mary
Thomas
Alice
Michael
Gordon
Gary
Hannah
Sally
Richard
Colin
Emma
Paige
John
Alex

Then you can get some random teams from this as follows:

$players = Import-Csv .\players.csv
$teamSize = 3
$maxTeams = [math]::Floor($players.Count/$teamSize)

$teams = @{}

$shuffled = $players | Get-Random -Count $players.Count

$shuffled |
    ForEach-Object { $i = 0 }{
        $teams["$($i % $maxTeams)"] += @($_.Player)
        $i++
    }

This leads to a hashtable similar to this:

Name Value                  
---- -----                  
0    {Alice, David, Mary}   
1    {Gordon, Colin, John}  
2    {Emma, Paige, Thomas}  
3    {Alex, Hannah, Richard}
4    {Sally, Michael, Gary} 

Adjust the $teamSize if you need more or fewer players in each team.

EDIT: Update based on @mklement0's comments. The above isn't exact in that it won't always give team sizes matching the original requirement. For example, for a list of 22 players:

TeamSize   Teams
--------   -----
1          1 x22
2          2 x11
3          3 x6 / 4 x1
4          4 x3 / 5 x2
5          5 x2 / 6 x2
6          7 x2 / 8 x1
7          7 x2 / 8 x1
8          11 x2
9          11 x2

It does, however, produce more evenly balanced teams if the $teamSize isn't too close to half the total. For a strict team size of 5, for example, you would end up with 4 teams of 5 and 1 team of 2, which might be too much of a mis-match depending on the scenario, but this gives 2 teams of 5 and 2 of 6, which might be 'fairer'.

Anyway, @mklement0 's enhancements produce a more strict adherance to the requirement. Here's the code for that:

$players = Import-Csv .\players.csv
$teamSize = 3
$maxTeams = [math]::Ceiling($players.Count/$teamSize)

$teams = @{}

$shuffled = $players | Get-Random -Count $players.Count

$shuffled |
    ForEach-Object { $i = 0 }{
        $teams["$([Math]::Floor($i / $teamSize))"] += @($_.Player)
        $i++
    }

For comparison, here's the teams this produces:

TeamSize   Teams
--------   -----
1          1 x22
2          2 x11
3          3 x7 / 1 x1
4          5 x4 / 2 x1
5          5 x4 / 2 x1
6          6 x3 / 4 x1
7          7 x3 / 1 x1
8          8 x2 / 6 x1
9          9 x2 / 4 x1
boxdog
  • 7,894
  • 2
  • 18
  • 27
0

A possible solution would be:

$users = import-csv "C:\Users\Bruger\Dokumenter\Esport_liste.csv" -Header "User"

$i = 0
$team = 1
$users | Sort-Object { Get-Random } | foreach {

    if(($i % 3) -eq 0){ " "; "Team $($team)"; $team++ }
    $_.User
    $i++
}

I won't explain it further. Try to understand it and ask in the comments, if further help is needed.

TobyU
  • 3,718
  • 2
  • 21
  • 32
  • Thanks works like a charm! If I will like to add something like Team 1, Team 2, Team 3 and so on. How can I merge that into the code? – Kunak Nov 14 '18 at 10:57
  • I've added the team names. – TobyU Nov 14 '18 at 11:55
  • This is a good start, and offers a nice _display_ of what the teams would be, but it doesn't create _data structures_ for the teams. `... | Sort-Object { Get-Random }` is an elegant way to shuffle a collection of unknown size, but if the collection size is known in advance, `... | Get-Random -Count` is much faster. With small input arrays that won't matter, however. – mklement0 Nov 15 '18 at 00:07