Create two random teams from a list of playersFunction that Loads a Random Image from an ArrayGenerating new...

Why would an invisible personal shield be necessary?

My employer is refusing to give me the pay that was advertised after an internal job move

Unknown indication below upper stave

What are the cons of stateless password generators?

Why does calling cout.operator<<(const char*) print the address instead of the character string?

What force enables us to walk? Friction or normal reaction?

What Marvel character has this 'W' symbol?

Should I intervene when a colleague in a different department makes students run laps as part of their grade?

Why are subdominants unstable?

Would it take any sort of amendment to make DC a state?

Exploiting the delay when a festival ticket is scanned

Reading electrical clamp tester higher voltage/amp 400A

Can machine learning learn a function like finding maximum from a list?

Antonym of "Megalomania"

How do discovery writers hibernate?

Bouncing map back into its bounds, after user dragged it out

What clothes would flying-people wear?

Can I attune a Circlet of Human Perfection to my animated skeletons to allow them to blend in and speak?

Why don't short runways use ramps for takeoff?

How should I quote American English speakers in a British English essay?

On the sensitivity conjecture?

Best Ergonomic Design for a handheld ranged weapon

How to efficiently shred a lot of cabbage?

Raindrops in Python



Create two random teams from a list of players


Function that Loads a Random Image from an ArrayGenerating new random items from a listCreate a list of random numbers with sum = nOnly using randint, create a random list of unique numbersDisplay four random entries from an arrayNCAA Pool - Generate random teams for a list of playersConditionally selecting random element from arrayGenerate cryptographically secure random numbers in a specific rangeCreate two arrays duplicate codeSelecting random elements from a `IList` with no repetitions






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







3












$begingroup$


The task is to create two random teams from a list of players.



Given an example of players = ["John", "Mike", "Alice", "Bob"]



One example random team would be:



team1 = ["Mike", "Alice"];
team2 = ["John", "Bob"];


This is my solution but I'm not sure how efficient it is because random can create same number for a number of times.



The question to separate equally and randomly without repeating the same player.



using System;
using System.Collections.Generic;

public class Program
{

public static void Main(string[] args)
{
Random rnd = new Random();
var numbers = new List<int>();

var ilkListe = new List<int>();

var ikinciListe = new List<int>();

numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
numbers.Add(4);
numbers.Add(5);
numbers.Add(6);
numbers.Add(7);
numbers.Add(8);
numbers.Add(9);
numbers.Add(10);
Console.WriteLine("LIST 1: " + numbers.Count);

do {
int sayi = numbers[rnd.Next(numbers.Count)];
if (!(ilkListe.Contains(sayi))) {
Console.WriteLine(sayi);
ilkListe.Add(sayi);
}
}

while (ilkListe.Count < numbers.Count / 2);

Console.WriteLine("Ikinci liste");

do {
int sayi = numbers[rnd.Next(numbers.Count)];
if (!(ilkListe.Contains(sayi)) && !(ikinciListe.Contains(sayi))) {
Console.WriteLine(sayi);
ikinciListe.Add(sayi);
}
}

while (ikinciListe.Count < numbers.Count / 2);
}
}









share|improve this question









New contributor



esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$










  • 3




    $begingroup$
    Thanks for updating. I've looked through your code and it does seem like it does what it is supposed to do but in an inefficient way, so you've come to the right place.
    $endgroup$
    – Simon Forsberg
    7 hours ago










  • $begingroup$
    @dfhwze it does not matter actually. The idea is same. I was just trying to simulate the task in an online editor.
    $endgroup$
    – esilik
    7 hours ago






  • 3




    $begingroup$
    I don't have time today to write an answer, but you should consider shuffling the array, then dividing into the two teams. That completes in deterministic time, whereas there's no guarantee that the presented algorithm will terminate.
    $endgroup$
    – Toby Speight
    5 hours ago










  • $begingroup$
    @Toby Speight thank you. "shuffling the array" do too much.
    $endgroup$
    – esilik
    4 hours ago










  • $begingroup$
    Actually: better than shuffling is simply to iterate through the elements, and assign each to a team (with 50% probability) until one of the teams is fully populated (effectively, a partial shuffle).
    $endgroup$
    – Toby Speight
    11 mins ago


















3












$begingroup$


The task is to create two random teams from a list of players.



Given an example of players = ["John", "Mike", "Alice", "Bob"]



One example random team would be:



team1 = ["Mike", "Alice"];
team2 = ["John", "Bob"];


This is my solution but I'm not sure how efficient it is because random can create same number for a number of times.



The question to separate equally and randomly without repeating the same player.



using System;
using System.Collections.Generic;

public class Program
{

public static void Main(string[] args)
{
Random rnd = new Random();
var numbers = new List<int>();

var ilkListe = new List<int>();

var ikinciListe = new List<int>();

numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
numbers.Add(4);
numbers.Add(5);
numbers.Add(6);
numbers.Add(7);
numbers.Add(8);
numbers.Add(9);
numbers.Add(10);
Console.WriteLine("LIST 1: " + numbers.Count);

do {
int sayi = numbers[rnd.Next(numbers.Count)];
if (!(ilkListe.Contains(sayi))) {
Console.WriteLine(sayi);
ilkListe.Add(sayi);
}
}

while (ilkListe.Count < numbers.Count / 2);

Console.WriteLine("Ikinci liste");

do {
int sayi = numbers[rnd.Next(numbers.Count)];
if (!(ilkListe.Contains(sayi)) && !(ikinciListe.Contains(sayi))) {
Console.WriteLine(sayi);
ikinciListe.Add(sayi);
}
}

while (ikinciListe.Count < numbers.Count / 2);
}
}









share|improve this question









New contributor



esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$










  • 3




    $begingroup$
    Thanks for updating. I've looked through your code and it does seem like it does what it is supposed to do but in an inefficient way, so you've come to the right place.
    $endgroup$
    – Simon Forsberg
    7 hours ago










  • $begingroup$
    @dfhwze it does not matter actually. The idea is same. I was just trying to simulate the task in an online editor.
    $endgroup$
    – esilik
    7 hours ago






  • 3




    $begingroup$
    I don't have time today to write an answer, but you should consider shuffling the array, then dividing into the two teams. That completes in deterministic time, whereas there's no guarantee that the presented algorithm will terminate.
    $endgroup$
    – Toby Speight
    5 hours ago










  • $begingroup$
    @Toby Speight thank you. "shuffling the array" do too much.
    $endgroup$
    – esilik
    4 hours ago










  • $begingroup$
    Actually: better than shuffling is simply to iterate through the elements, and assign each to a team (with 50% probability) until one of the teams is fully populated (effectively, a partial shuffle).
    $endgroup$
    – Toby Speight
    11 mins ago














3












3








3





$begingroup$


The task is to create two random teams from a list of players.



Given an example of players = ["John", "Mike", "Alice", "Bob"]



One example random team would be:



team1 = ["Mike", "Alice"];
team2 = ["John", "Bob"];


This is my solution but I'm not sure how efficient it is because random can create same number for a number of times.



The question to separate equally and randomly without repeating the same player.



using System;
using System.Collections.Generic;

public class Program
{

public static void Main(string[] args)
{
Random rnd = new Random();
var numbers = new List<int>();

var ilkListe = new List<int>();

var ikinciListe = new List<int>();

numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
numbers.Add(4);
numbers.Add(5);
numbers.Add(6);
numbers.Add(7);
numbers.Add(8);
numbers.Add(9);
numbers.Add(10);
Console.WriteLine("LIST 1: " + numbers.Count);

do {
int sayi = numbers[rnd.Next(numbers.Count)];
if (!(ilkListe.Contains(sayi))) {
Console.WriteLine(sayi);
ilkListe.Add(sayi);
}
}

while (ilkListe.Count < numbers.Count / 2);

Console.WriteLine("Ikinci liste");

do {
int sayi = numbers[rnd.Next(numbers.Count)];
if (!(ilkListe.Contains(sayi)) && !(ikinciListe.Contains(sayi))) {
Console.WriteLine(sayi);
ikinciListe.Add(sayi);
}
}

while (ikinciListe.Count < numbers.Count / 2);
}
}









share|improve this question









New contributor



esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$




The task is to create two random teams from a list of players.



Given an example of players = ["John", "Mike", "Alice", "Bob"]



One example random team would be:



team1 = ["Mike", "Alice"];
team2 = ["John", "Bob"];


This is my solution but I'm not sure how efficient it is because random can create same number for a number of times.



The question to separate equally and randomly without repeating the same player.



using System;
using System.Collections.Generic;

public class Program
{

public static void Main(string[] args)
{
Random rnd = new Random();
var numbers = new List<int>();

var ilkListe = new List<int>();

var ikinciListe = new List<int>();

numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
numbers.Add(4);
numbers.Add(5);
numbers.Add(6);
numbers.Add(7);
numbers.Add(8);
numbers.Add(9);
numbers.Add(10);
Console.WriteLine("LIST 1: " + numbers.Count);

do {
int sayi = numbers[rnd.Next(numbers.Count)];
if (!(ilkListe.Contains(sayi))) {
Console.WriteLine(sayi);
ilkListe.Add(sayi);
}
}

while (ilkListe.Count < numbers.Count / 2);

Console.WriteLine("Ikinci liste");

do {
int sayi = numbers[rnd.Next(numbers.Count)];
if (!(ilkListe.Contains(sayi)) && !(ikinciListe.Contains(sayi))) {
Console.WriteLine(sayi);
ikinciListe.Add(sayi);
}
}

while (ikinciListe.Count < numbers.Count / 2);
}
}






c# array random






share|improve this question









New contributor



esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










share|improve this question









New contributor



esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








share|improve this question




share|improve this question








edited 7 hours ago









Simon Forsberg

49.5k7 gold badges131 silver badges288 bronze badges




49.5k7 gold badges131 silver badges288 bronze badges






New contributor



esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








asked 8 hours ago









esilikesilik

1324 bronze badges




1324 bronze badges




New contributor



esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




New contributor




esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.













  • 3




    $begingroup$
    Thanks for updating. I've looked through your code and it does seem like it does what it is supposed to do but in an inefficient way, so you've come to the right place.
    $endgroup$
    – Simon Forsberg
    7 hours ago










  • $begingroup$
    @dfhwze it does not matter actually. The idea is same. I was just trying to simulate the task in an online editor.
    $endgroup$
    – esilik
    7 hours ago






  • 3




    $begingroup$
    I don't have time today to write an answer, but you should consider shuffling the array, then dividing into the two teams. That completes in deterministic time, whereas there's no guarantee that the presented algorithm will terminate.
    $endgroup$
    – Toby Speight
    5 hours ago










  • $begingroup$
    @Toby Speight thank you. "shuffling the array" do too much.
    $endgroup$
    – esilik
    4 hours ago










  • $begingroup$
    Actually: better than shuffling is simply to iterate through the elements, and assign each to a team (with 50% probability) until one of the teams is fully populated (effectively, a partial shuffle).
    $endgroup$
    – Toby Speight
    11 mins ago














  • 3




    $begingroup$
    Thanks for updating. I've looked through your code and it does seem like it does what it is supposed to do but in an inefficient way, so you've come to the right place.
    $endgroup$
    – Simon Forsberg
    7 hours ago










  • $begingroup$
    @dfhwze it does not matter actually. The idea is same. I was just trying to simulate the task in an online editor.
    $endgroup$
    – esilik
    7 hours ago






  • 3




    $begingroup$
    I don't have time today to write an answer, but you should consider shuffling the array, then dividing into the two teams. That completes in deterministic time, whereas there's no guarantee that the presented algorithm will terminate.
    $endgroup$
    – Toby Speight
    5 hours ago










  • $begingroup$
    @Toby Speight thank you. "shuffling the array" do too much.
    $endgroup$
    – esilik
    4 hours ago










  • $begingroup$
    Actually: better than shuffling is simply to iterate through the elements, and assign each to a team (with 50% probability) until one of the teams is fully populated (effectively, a partial shuffle).
    $endgroup$
    – Toby Speight
    11 mins ago








3




3




$begingroup$
Thanks for updating. I've looked through your code and it does seem like it does what it is supposed to do but in an inefficient way, so you've come to the right place.
$endgroup$
– Simon Forsberg
7 hours ago




$begingroup$
Thanks for updating. I've looked through your code and it does seem like it does what it is supposed to do but in an inefficient way, so you've come to the right place.
$endgroup$
– Simon Forsberg
7 hours ago












$begingroup$
@dfhwze it does not matter actually. The idea is same. I was just trying to simulate the task in an online editor.
$endgroup$
– esilik
7 hours ago




$begingroup$
@dfhwze it does not matter actually. The idea is same. I was just trying to simulate the task in an online editor.
$endgroup$
– esilik
7 hours ago




3




3




$begingroup$
I don't have time today to write an answer, but you should consider shuffling the array, then dividing into the two teams. That completes in deterministic time, whereas there's no guarantee that the presented algorithm will terminate.
$endgroup$
– Toby Speight
5 hours ago




$begingroup$
I don't have time today to write an answer, but you should consider shuffling the array, then dividing into the two teams. That completes in deterministic time, whereas there's no guarantee that the presented algorithm will terminate.
$endgroup$
– Toby Speight
5 hours ago












$begingroup$
@Toby Speight thank you. "shuffling the array" do too much.
$endgroup$
– esilik
4 hours ago




$begingroup$
@Toby Speight thank you. "shuffling the array" do too much.
$endgroup$
– esilik
4 hours ago












$begingroup$
Actually: better than shuffling is simply to iterate through the elements, and assign each to a team (with 50% probability) until one of the teams is fully populated (effectively, a partial shuffle).
$endgroup$
– Toby Speight
11 mins ago




$begingroup$
Actually: better than shuffling is simply to iterate through the elements, and assign each to a team (with 50% probability) until one of the teams is fully populated (effectively, a partial shuffle).
$endgroup$
– Toby Speight
11 mins ago










5 Answers
5






active

oldest

votes


















7












$begingroup$

Review




  • Don't use the main entry point to implement an algorithm. Create a method instead.

  • Think about how to allow this method to be usable for all kinds of types, not just integers. You have implemented the algorithm for integers, yet you show an example with strings.

  • When creating an algorithm, surely you have made some unit tests, at least for the happy paths. Feel free to include them in the question.

  • Use clear variable names, and stick to one written language.

  • Don't mix algorithm logic with Console output.


A possible method signature could be:



public static IEnumerable<IEnumerable<T>> SplitRandom<T>(
this IEnumerable<T> source, int targetCount)
{
// .. algorithm implementation
}


Called as..



var names = new [] { "John", "Mike", "Alice", "Bob" };
var teams = names.SplitRandom(2);


Or as..



var numbers = Enumrable.Range(1, 10);
var numberGroups = numbers.SplitRandom(2);





share|improve this answer











$endgroup$























    1












    $begingroup$

    using System;
    using System.Collections.Generic;

    public class Program
    {

    public static void Main(string[] args)
    {
    List<string> players = new List<string>(new string[]{ "John", "Mike", "Kate", "Michael" });

    List<string> randomPlayers = ShuffleList<string>(players);

    List<string> team1 = randomPlayers.GetRange(0, (randomPlayers.Count - 1) / 2);
    List<string> team2 = randomPlayers.GetRange((randomPlayers.Count - 1) / 2, (randomPlayers.Count - 1));
    }

    public static List<E> ShuffleList<E>(List<E> inputList)
    {
    List<E> randomList = new List<E>();

    Random r = new Random();
    int randomIndex = 0;
    while (inputList.Count > 0)
    {
    randomIndex = r.Next(0, inputList.Count); //Choose a random object in the list
    randomList.Add(inputList[randomIndex]); //add it to the new, random list
    inputList.RemoveAt(randomIndex); //remove to avoid duplicates
    }

    return randomList; //return the new random list
    }
    }


    After a little search of "array shuffle keyword", rewrite the code.






    share|improve this answer








    New contributor



    esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.





    $endgroup$















    • $begingroup$
      Welcome to Code Review! Just a friendly reminder that self-answers should still be in the form of a review - you're expected to explain what's wrong with the original code, rather than simply posting a replacement. You'll find more guidance in the help center (sorry, I don't have time to look it up for you right now - I'm in the middle of a very busy spell).
      $endgroup$
      – Toby Speight
      7 mins ago



















    0












    $begingroup$

    While your new solution does look somewhat better than the original, I would suggest that constantly removing elements from the list can be quite expensive. I would suggest shuffling or randomly sorting the list then simply divvying up the players to the teams.



    Also you're still putting the implementation in Main, instead of calling a method.



    Instead of hardcoding everything for 2 teams I would be in favor of allowing any number of teams as long as it's an exact divisor of the number of players.



    Instead of multidimensional lists, I would use a Dictionary where the Key is the name of the team and the players names are in a list.



    It could look something like this:



    public static Dictionary<int,List<T>> MakeTeams<T>(this List<T> playerList, int numTeams)
    {

    int count = playerList.Count();
    if(count % numTeams != 0)
    {
    throw new ArgumentException("The number of players must be a multiple of numTeams to get even distribution of players");
    }
    var randomList = playerList.OrderBy(x => Guid.NewGuid()).ToList();
    var teams = (from int i in Enumerable.Range(0, count)
    let item = randomList[i]
    group item by (i % numTeams) into team
    select team).ToDictionary(team => team.Key, team => team.ToList());

    return teams;
    }


    This simply uses a number for the team name. If you wanted to get fancier with it you could add a string array of team names to use instead:



    public static Dictionary<string, List<T>> MakeTeams<T>(this List<T> playerList, int numTeams, string[] teamNames)
    {
    if(teamNames.Length < numTeams)
    {
    throw new ArgumentException("The number of team names must be equal to or greater than numTeams");
    }
    int count = playerList.Count();
    if (count % numTeams != 0)
    {
    throw new ArgumentException("The number of players must be a multiple of numTeams to get even distribution of players");
    }
    var randomList = playerList.OrderBy(x => Guid.NewGuid()).ToList();
    var teams = (from int i in Enumerable.Range(0, count)
    let item = randomList[i]
    group item by (i % numTeams) into team
    select team).ToDictionary(team => teamNames[team.Key], team => team.ToList());

    return teams;
    }





    share|improve this answer









    $endgroup$















    • $begingroup$
      Couple of things: Make the dictionary keys a generic type as well. Don't ask how many teams there are, just count how many keys you were given. Don't use random-guid-sort to shuffle (lengthy discussion in comments).
      $endgroup$
      – ShapeOfMatter
      2 hours ago



















    0












    $begingroup$

    All of dfhwze's points are spot-on, and the only thing I can think of to add to his type-signature is that if you're unfamiliar with all of the syntax he's using that's ok.
    (If you want to learn the stuff in question, search for "inheritance" (or "interface"), "generics", "extension methods", and possibly "generators" or "yield".)



    Regarding your actual algorithm:



    The big red flag that your current algorithm isn't good is that you have two nearly-identical loops. That they happen to be while loops is a small red flag, which you noticed indirectly when you noted that rnd.Next() can yield duplicates.



    The algorithm you probably want is to first shuffle your source list, and then take sequential runs from it as needed.
    Stack Exchange gives us usable implementations of both those steps. Only copy-paste them if you understand how they work and you want those exact methods lying around your code-base; most of the time it's better to re-write these things so that you're making the "details" decisions for yourself.





    • This answer gives us a nice implementation of The Fisher–Yates shuffle, which is efficient and appropriate.


    • This answer gives us tidy slicing. (What exactly happens if source.Count / (Double)size isn't an integer?)


    There are some details that probably matter, like whether or not the original order of the elements needs to be preserved, or what should happen if the source list isn't evenly divisible into the number of buckets in question.



    And once you've resolved all of that, since you asked about efficiency, we can return to dfhwze's function signature. Specifically, this IEnumerable<T> source is taken as an enumerable collection; the Fisher–Yates shuffle shuffles a list in place. It's very tempting to change the argument to this IList<T> source, so that if the calling context already has a list, we're can just use that one instead of calling source.ToList(). If you do it that way you'll have written a function that returns a computed value and modifies the contents of its argument; strongly consider not doing that.






    share|improve this answer









    $endgroup$























      -2












      $begingroup$

      Below is a slightly improved algorithm of the problem.
      This uses one while loop as opposed to two.



      using System;
      using System.Collections.Generic;

      class Program
      {
      static List<String> AllPlayers = new List<String>();

      static List<string> Team1 = new List<string>();
      static List<string> Team2 = new List<string>();

      static void Main(string[] args)
      {

      AllPlayers.Add("A1");
      AllPlayers.Add("A2");
      AllPlayers.Add("A3");
      AllPlayers.Add("A4");
      AllPlayers.Add("A5");
      AllPlayers.Add("A6");


      AllotPlayers();


      Console.WriteLine("Team1");
      foreach (var p in Team1)
      Console.Write(" " + p + " ,");
      Console.WriteLine();
      Console.WriteLine("Team2");
      foreach (var p in Team2)
      Console.Write(" " + p + " ,");
      }

      static void AllotPlayers()
      {
      Random rnd = new Random();
      int count = 0;
      bool firstTeam = false;
      string player = string.Empty;
      int index = -1;
      do
      {
      index = rnd.Next(AllPlayers.Count);
      player = AllPlayers[index];
      if (player == string.Empty) continue;

      AllPlayers[index] = "";
      if (firstTeam) Team2.Add(player);
      else Team1.Add(player);
      firstTeam = !firstTeam;
      count++;
      } while (count < AllPlayers.Count);
      }
      }





      share|improve this answer









      $endgroup$











      • 3




        $begingroup$
        You've shown an alternative algorithm, but haven't reviewed the code at all. Please critique the code posted; I think that "This uses one while loop as opposed to two" is a little too brief to be a proper review. Thanks.
        $endgroup$
        – Toby Speight
        5 hours ago










      • $begingroup$
        The point of code review is to provide suggestions to improve the posters code rather than provide alternate solutions. This answer only provides an alternate solution without an insightful observation. Alternate solutions may be deleted either by the community or the moderators.
        $endgroup$
        – pacmaninbw
        5 hours ago
















      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "196"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });






      esilik is a new contributor. Be nice, and check out our Code of Conduct.










      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f225287%2fcreate-two-random-teams-from-a-list-of-players%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      7












      $begingroup$

      Review




      • Don't use the main entry point to implement an algorithm. Create a method instead.

      • Think about how to allow this method to be usable for all kinds of types, not just integers. You have implemented the algorithm for integers, yet you show an example with strings.

      • When creating an algorithm, surely you have made some unit tests, at least for the happy paths. Feel free to include them in the question.

      • Use clear variable names, and stick to one written language.

      • Don't mix algorithm logic with Console output.


      A possible method signature could be:



      public static IEnumerable<IEnumerable<T>> SplitRandom<T>(
      this IEnumerable<T> source, int targetCount)
      {
      // .. algorithm implementation
      }


      Called as..



      var names = new [] { "John", "Mike", "Alice", "Bob" };
      var teams = names.SplitRandom(2);


      Or as..



      var numbers = Enumrable.Range(1, 10);
      var numberGroups = numbers.SplitRandom(2);





      share|improve this answer











      $endgroup$




















        7












        $begingroup$

        Review




        • Don't use the main entry point to implement an algorithm. Create a method instead.

        • Think about how to allow this method to be usable for all kinds of types, not just integers. You have implemented the algorithm for integers, yet you show an example with strings.

        • When creating an algorithm, surely you have made some unit tests, at least for the happy paths. Feel free to include them in the question.

        • Use clear variable names, and stick to one written language.

        • Don't mix algorithm logic with Console output.


        A possible method signature could be:



        public static IEnumerable<IEnumerable<T>> SplitRandom<T>(
        this IEnumerable<T> source, int targetCount)
        {
        // .. algorithm implementation
        }


        Called as..



        var names = new [] { "John", "Mike", "Alice", "Bob" };
        var teams = names.SplitRandom(2);


        Or as..



        var numbers = Enumrable.Range(1, 10);
        var numberGroups = numbers.SplitRandom(2);





        share|improve this answer











        $endgroup$


















          7












          7








          7





          $begingroup$

          Review




          • Don't use the main entry point to implement an algorithm. Create a method instead.

          • Think about how to allow this method to be usable for all kinds of types, not just integers. You have implemented the algorithm for integers, yet you show an example with strings.

          • When creating an algorithm, surely you have made some unit tests, at least for the happy paths. Feel free to include them in the question.

          • Use clear variable names, and stick to one written language.

          • Don't mix algorithm logic with Console output.


          A possible method signature could be:



          public static IEnumerable<IEnumerable<T>> SplitRandom<T>(
          this IEnumerable<T> source, int targetCount)
          {
          // .. algorithm implementation
          }


          Called as..



          var names = new [] { "John", "Mike", "Alice", "Bob" };
          var teams = names.SplitRandom(2);


          Or as..



          var numbers = Enumrable.Range(1, 10);
          var numberGroups = numbers.SplitRandom(2);





          share|improve this answer











          $endgroup$



          Review




          • Don't use the main entry point to implement an algorithm. Create a method instead.

          • Think about how to allow this method to be usable for all kinds of types, not just integers. You have implemented the algorithm for integers, yet you show an example with strings.

          • When creating an algorithm, surely you have made some unit tests, at least for the happy paths. Feel free to include them in the question.

          • Use clear variable names, and stick to one written language.

          • Don't mix algorithm logic with Console output.


          A possible method signature could be:



          public static IEnumerable<IEnumerable<T>> SplitRandom<T>(
          this IEnumerable<T> source, int targetCount)
          {
          // .. algorithm implementation
          }


          Called as..



          var names = new [] { "John", "Mike", "Alice", "Bob" };
          var teams = names.SplitRandom(2);


          Or as..



          var numbers = Enumrable.Range(1, 10);
          var numberGroups = numbers.SplitRandom(2);






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 6 hours ago

























          answered 7 hours ago









          dfhwzedfhwze

          7,0511 gold badge15 silver badges44 bronze badges




          7,0511 gold badge15 silver badges44 bronze badges




























              1












              $begingroup$

              using System;
              using System.Collections.Generic;

              public class Program
              {

              public static void Main(string[] args)
              {
              List<string> players = new List<string>(new string[]{ "John", "Mike", "Kate", "Michael" });

              List<string> randomPlayers = ShuffleList<string>(players);

              List<string> team1 = randomPlayers.GetRange(0, (randomPlayers.Count - 1) / 2);
              List<string> team2 = randomPlayers.GetRange((randomPlayers.Count - 1) / 2, (randomPlayers.Count - 1));
              }

              public static List<E> ShuffleList<E>(List<E> inputList)
              {
              List<E> randomList = new List<E>();

              Random r = new Random();
              int randomIndex = 0;
              while (inputList.Count > 0)
              {
              randomIndex = r.Next(0, inputList.Count); //Choose a random object in the list
              randomList.Add(inputList[randomIndex]); //add it to the new, random list
              inputList.RemoveAt(randomIndex); //remove to avoid duplicates
              }

              return randomList; //return the new random list
              }
              }


              After a little search of "array shuffle keyword", rewrite the code.






              share|improve this answer








              New contributor



              esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.





              $endgroup$















              • $begingroup$
                Welcome to Code Review! Just a friendly reminder that self-answers should still be in the form of a review - you're expected to explain what's wrong with the original code, rather than simply posting a replacement. You'll find more guidance in the help center (sorry, I don't have time to look it up for you right now - I'm in the middle of a very busy spell).
                $endgroup$
                – Toby Speight
                7 mins ago
















              1












              $begingroup$

              using System;
              using System.Collections.Generic;

              public class Program
              {

              public static void Main(string[] args)
              {
              List<string> players = new List<string>(new string[]{ "John", "Mike", "Kate", "Michael" });

              List<string> randomPlayers = ShuffleList<string>(players);

              List<string> team1 = randomPlayers.GetRange(0, (randomPlayers.Count - 1) / 2);
              List<string> team2 = randomPlayers.GetRange((randomPlayers.Count - 1) / 2, (randomPlayers.Count - 1));
              }

              public static List<E> ShuffleList<E>(List<E> inputList)
              {
              List<E> randomList = new List<E>();

              Random r = new Random();
              int randomIndex = 0;
              while (inputList.Count > 0)
              {
              randomIndex = r.Next(0, inputList.Count); //Choose a random object in the list
              randomList.Add(inputList[randomIndex]); //add it to the new, random list
              inputList.RemoveAt(randomIndex); //remove to avoid duplicates
              }

              return randomList; //return the new random list
              }
              }


              After a little search of "array shuffle keyword", rewrite the code.






              share|improve this answer








              New contributor



              esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.





              $endgroup$















              • $begingroup$
                Welcome to Code Review! Just a friendly reminder that self-answers should still be in the form of a review - you're expected to explain what's wrong with the original code, rather than simply posting a replacement. You'll find more guidance in the help center (sorry, I don't have time to look it up for you right now - I'm in the middle of a very busy spell).
                $endgroup$
                – Toby Speight
                7 mins ago














              1












              1








              1





              $begingroup$

              using System;
              using System.Collections.Generic;

              public class Program
              {

              public static void Main(string[] args)
              {
              List<string> players = new List<string>(new string[]{ "John", "Mike", "Kate", "Michael" });

              List<string> randomPlayers = ShuffleList<string>(players);

              List<string> team1 = randomPlayers.GetRange(0, (randomPlayers.Count - 1) / 2);
              List<string> team2 = randomPlayers.GetRange((randomPlayers.Count - 1) / 2, (randomPlayers.Count - 1));
              }

              public static List<E> ShuffleList<E>(List<E> inputList)
              {
              List<E> randomList = new List<E>();

              Random r = new Random();
              int randomIndex = 0;
              while (inputList.Count > 0)
              {
              randomIndex = r.Next(0, inputList.Count); //Choose a random object in the list
              randomList.Add(inputList[randomIndex]); //add it to the new, random list
              inputList.RemoveAt(randomIndex); //remove to avoid duplicates
              }

              return randomList; //return the new random list
              }
              }


              After a little search of "array shuffle keyword", rewrite the code.






              share|improve this answer








              New contributor



              esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.





              $endgroup$



              using System;
              using System.Collections.Generic;

              public class Program
              {

              public static void Main(string[] args)
              {
              List<string> players = new List<string>(new string[]{ "John", "Mike", "Kate", "Michael" });

              List<string> randomPlayers = ShuffleList<string>(players);

              List<string> team1 = randomPlayers.GetRange(0, (randomPlayers.Count - 1) / 2);
              List<string> team2 = randomPlayers.GetRange((randomPlayers.Count - 1) / 2, (randomPlayers.Count - 1));
              }

              public static List<E> ShuffleList<E>(List<E> inputList)
              {
              List<E> randomList = new List<E>();

              Random r = new Random();
              int randomIndex = 0;
              while (inputList.Count > 0)
              {
              randomIndex = r.Next(0, inputList.Count); //Choose a random object in the list
              randomList.Add(inputList[randomIndex]); //add it to the new, random list
              inputList.RemoveAt(randomIndex); //remove to avoid duplicates
              }

              return randomList; //return the new random list
              }
              }


              After a little search of "array shuffle keyword", rewrite the code.







              share|improve this answer








              New contributor



              esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.








              share|improve this answer



              share|improve this answer






              New contributor



              esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.








              answered 4 hours ago









              esilikesilik

              1324 bronze badges




              1324 bronze badges




              New contributor



              esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.




              New contributor




              esilik is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.

















              • $begingroup$
                Welcome to Code Review! Just a friendly reminder that self-answers should still be in the form of a review - you're expected to explain what's wrong with the original code, rather than simply posting a replacement. You'll find more guidance in the help center (sorry, I don't have time to look it up for you right now - I'm in the middle of a very busy spell).
                $endgroup$
                – Toby Speight
                7 mins ago


















              • $begingroup$
                Welcome to Code Review! Just a friendly reminder that self-answers should still be in the form of a review - you're expected to explain what's wrong with the original code, rather than simply posting a replacement. You'll find more guidance in the help center (sorry, I don't have time to look it up for you right now - I'm in the middle of a very busy spell).
                $endgroup$
                – Toby Speight
                7 mins ago
















              $begingroup$
              Welcome to Code Review! Just a friendly reminder that self-answers should still be in the form of a review - you're expected to explain what's wrong with the original code, rather than simply posting a replacement. You'll find more guidance in the help center (sorry, I don't have time to look it up for you right now - I'm in the middle of a very busy spell).
              $endgroup$
              – Toby Speight
              7 mins ago




              $begingroup$
              Welcome to Code Review! Just a friendly reminder that self-answers should still be in the form of a review - you're expected to explain what's wrong with the original code, rather than simply posting a replacement. You'll find more guidance in the help center (sorry, I don't have time to look it up for you right now - I'm in the middle of a very busy spell).
              $endgroup$
              – Toby Speight
              7 mins ago











              0












              $begingroup$

              While your new solution does look somewhat better than the original, I would suggest that constantly removing elements from the list can be quite expensive. I would suggest shuffling or randomly sorting the list then simply divvying up the players to the teams.



              Also you're still putting the implementation in Main, instead of calling a method.



              Instead of hardcoding everything for 2 teams I would be in favor of allowing any number of teams as long as it's an exact divisor of the number of players.



              Instead of multidimensional lists, I would use a Dictionary where the Key is the name of the team and the players names are in a list.



              It could look something like this:



              public static Dictionary<int,List<T>> MakeTeams<T>(this List<T> playerList, int numTeams)
              {

              int count = playerList.Count();
              if(count % numTeams != 0)
              {
              throw new ArgumentException("The number of players must be a multiple of numTeams to get even distribution of players");
              }
              var randomList = playerList.OrderBy(x => Guid.NewGuid()).ToList();
              var teams = (from int i in Enumerable.Range(0, count)
              let item = randomList[i]
              group item by (i % numTeams) into team
              select team).ToDictionary(team => team.Key, team => team.ToList());

              return teams;
              }


              This simply uses a number for the team name. If you wanted to get fancier with it you could add a string array of team names to use instead:



              public static Dictionary<string, List<T>> MakeTeams<T>(this List<T> playerList, int numTeams, string[] teamNames)
              {
              if(teamNames.Length < numTeams)
              {
              throw new ArgumentException("The number of team names must be equal to or greater than numTeams");
              }
              int count = playerList.Count();
              if (count % numTeams != 0)
              {
              throw new ArgumentException("The number of players must be a multiple of numTeams to get even distribution of players");
              }
              var randomList = playerList.OrderBy(x => Guid.NewGuid()).ToList();
              var teams = (from int i in Enumerable.Range(0, count)
              let item = randomList[i]
              group item by (i % numTeams) into team
              select team).ToDictionary(team => teamNames[team.Key], team => team.ToList());

              return teams;
              }





              share|improve this answer









              $endgroup$















              • $begingroup$
                Couple of things: Make the dictionary keys a generic type as well. Don't ask how many teams there are, just count how many keys you were given. Don't use random-guid-sort to shuffle (lengthy discussion in comments).
                $endgroup$
                – ShapeOfMatter
                2 hours ago
















              0












              $begingroup$

              While your new solution does look somewhat better than the original, I would suggest that constantly removing elements from the list can be quite expensive. I would suggest shuffling or randomly sorting the list then simply divvying up the players to the teams.



              Also you're still putting the implementation in Main, instead of calling a method.



              Instead of hardcoding everything for 2 teams I would be in favor of allowing any number of teams as long as it's an exact divisor of the number of players.



              Instead of multidimensional lists, I would use a Dictionary where the Key is the name of the team and the players names are in a list.



              It could look something like this:



              public static Dictionary<int,List<T>> MakeTeams<T>(this List<T> playerList, int numTeams)
              {

              int count = playerList.Count();
              if(count % numTeams != 0)
              {
              throw new ArgumentException("The number of players must be a multiple of numTeams to get even distribution of players");
              }
              var randomList = playerList.OrderBy(x => Guid.NewGuid()).ToList();
              var teams = (from int i in Enumerable.Range(0, count)
              let item = randomList[i]
              group item by (i % numTeams) into team
              select team).ToDictionary(team => team.Key, team => team.ToList());

              return teams;
              }


              This simply uses a number for the team name. If you wanted to get fancier with it you could add a string array of team names to use instead:



              public static Dictionary<string, List<T>> MakeTeams<T>(this List<T> playerList, int numTeams, string[] teamNames)
              {
              if(teamNames.Length < numTeams)
              {
              throw new ArgumentException("The number of team names must be equal to or greater than numTeams");
              }
              int count = playerList.Count();
              if (count % numTeams != 0)
              {
              throw new ArgumentException("The number of players must be a multiple of numTeams to get even distribution of players");
              }
              var randomList = playerList.OrderBy(x => Guid.NewGuid()).ToList();
              var teams = (from int i in Enumerable.Range(0, count)
              let item = randomList[i]
              group item by (i % numTeams) into team
              select team).ToDictionary(team => teamNames[team.Key], team => team.ToList());

              return teams;
              }





              share|improve this answer









              $endgroup$















              • $begingroup$
                Couple of things: Make the dictionary keys a generic type as well. Don't ask how many teams there are, just count how many keys you were given. Don't use random-guid-sort to shuffle (lengthy discussion in comments).
                $endgroup$
                – ShapeOfMatter
                2 hours ago














              0












              0








              0





              $begingroup$

              While your new solution does look somewhat better than the original, I would suggest that constantly removing elements from the list can be quite expensive. I would suggest shuffling or randomly sorting the list then simply divvying up the players to the teams.



              Also you're still putting the implementation in Main, instead of calling a method.



              Instead of hardcoding everything for 2 teams I would be in favor of allowing any number of teams as long as it's an exact divisor of the number of players.



              Instead of multidimensional lists, I would use a Dictionary where the Key is the name of the team and the players names are in a list.



              It could look something like this:



              public static Dictionary<int,List<T>> MakeTeams<T>(this List<T> playerList, int numTeams)
              {

              int count = playerList.Count();
              if(count % numTeams != 0)
              {
              throw new ArgumentException("The number of players must be a multiple of numTeams to get even distribution of players");
              }
              var randomList = playerList.OrderBy(x => Guid.NewGuid()).ToList();
              var teams = (from int i in Enumerable.Range(0, count)
              let item = randomList[i]
              group item by (i % numTeams) into team
              select team).ToDictionary(team => team.Key, team => team.ToList());

              return teams;
              }


              This simply uses a number for the team name. If you wanted to get fancier with it you could add a string array of team names to use instead:



              public static Dictionary<string, List<T>> MakeTeams<T>(this List<T> playerList, int numTeams, string[] teamNames)
              {
              if(teamNames.Length < numTeams)
              {
              throw new ArgumentException("The number of team names must be equal to or greater than numTeams");
              }
              int count = playerList.Count();
              if (count % numTeams != 0)
              {
              throw new ArgumentException("The number of players must be a multiple of numTeams to get even distribution of players");
              }
              var randomList = playerList.OrderBy(x => Guid.NewGuid()).ToList();
              var teams = (from int i in Enumerable.Range(0, count)
              let item = randomList[i]
              group item by (i % numTeams) into team
              select team).ToDictionary(team => teamNames[team.Key], team => team.ToList());

              return teams;
              }





              share|improve this answer









              $endgroup$



              While your new solution does look somewhat better than the original, I would suggest that constantly removing elements from the list can be quite expensive. I would suggest shuffling or randomly sorting the list then simply divvying up the players to the teams.



              Also you're still putting the implementation in Main, instead of calling a method.



              Instead of hardcoding everything for 2 teams I would be in favor of allowing any number of teams as long as it's an exact divisor of the number of players.



              Instead of multidimensional lists, I would use a Dictionary where the Key is the name of the team and the players names are in a list.



              It could look something like this:



              public static Dictionary<int,List<T>> MakeTeams<T>(this List<T> playerList, int numTeams)
              {

              int count = playerList.Count();
              if(count % numTeams != 0)
              {
              throw new ArgumentException("The number of players must be a multiple of numTeams to get even distribution of players");
              }
              var randomList = playerList.OrderBy(x => Guid.NewGuid()).ToList();
              var teams = (from int i in Enumerable.Range(0, count)
              let item = randomList[i]
              group item by (i % numTeams) into team
              select team).ToDictionary(team => team.Key, team => team.ToList());

              return teams;
              }


              This simply uses a number for the team name. If you wanted to get fancier with it you could add a string array of team names to use instead:



              public static Dictionary<string, List<T>> MakeTeams<T>(this List<T> playerList, int numTeams, string[] teamNames)
              {
              if(teamNames.Length < numTeams)
              {
              throw new ArgumentException("The number of team names must be equal to or greater than numTeams");
              }
              int count = playerList.Count();
              if (count % numTeams != 0)
              {
              throw new ArgumentException("The number of players must be a multiple of numTeams to get even distribution of players");
              }
              var randomList = playerList.OrderBy(x => Guid.NewGuid()).ToList();
              var teams = (from int i in Enumerable.Range(0, count)
              let item = randomList[i]
              group item by (i % numTeams) into team
              select team).ToDictionary(team => teamNames[team.Key], team => team.ToList());

              return teams;
              }






              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered 3 hours ago









              tinstaafltinstaafl

              7,3661 gold badge9 silver badges31 bronze badges




              7,3661 gold badge9 silver badges31 bronze badges















              • $begingroup$
                Couple of things: Make the dictionary keys a generic type as well. Don't ask how many teams there are, just count how many keys you were given. Don't use random-guid-sort to shuffle (lengthy discussion in comments).
                $endgroup$
                – ShapeOfMatter
                2 hours ago


















              • $begingroup$
                Couple of things: Make the dictionary keys a generic type as well. Don't ask how many teams there are, just count how many keys you were given. Don't use random-guid-sort to shuffle (lengthy discussion in comments).
                $endgroup$
                – ShapeOfMatter
                2 hours ago
















              $begingroup$
              Couple of things: Make the dictionary keys a generic type as well. Don't ask how many teams there are, just count how many keys you were given. Don't use random-guid-sort to shuffle (lengthy discussion in comments).
              $endgroup$
              – ShapeOfMatter
              2 hours ago




              $begingroup$
              Couple of things: Make the dictionary keys a generic type as well. Don't ask how many teams there are, just count how many keys you were given. Don't use random-guid-sort to shuffle (lengthy discussion in comments).
              $endgroup$
              – ShapeOfMatter
              2 hours ago











              0












              $begingroup$

              All of dfhwze's points are spot-on, and the only thing I can think of to add to his type-signature is that if you're unfamiliar with all of the syntax he's using that's ok.
              (If you want to learn the stuff in question, search for "inheritance" (or "interface"), "generics", "extension methods", and possibly "generators" or "yield".)



              Regarding your actual algorithm:



              The big red flag that your current algorithm isn't good is that you have two nearly-identical loops. That they happen to be while loops is a small red flag, which you noticed indirectly when you noted that rnd.Next() can yield duplicates.



              The algorithm you probably want is to first shuffle your source list, and then take sequential runs from it as needed.
              Stack Exchange gives us usable implementations of both those steps. Only copy-paste them if you understand how they work and you want those exact methods lying around your code-base; most of the time it's better to re-write these things so that you're making the "details" decisions for yourself.





              • This answer gives us a nice implementation of The Fisher–Yates shuffle, which is efficient and appropriate.


              • This answer gives us tidy slicing. (What exactly happens if source.Count / (Double)size isn't an integer?)


              There are some details that probably matter, like whether or not the original order of the elements needs to be preserved, or what should happen if the source list isn't evenly divisible into the number of buckets in question.



              And once you've resolved all of that, since you asked about efficiency, we can return to dfhwze's function signature. Specifically, this IEnumerable<T> source is taken as an enumerable collection; the Fisher–Yates shuffle shuffles a list in place. It's very tempting to change the argument to this IList<T> source, so that if the calling context already has a list, we're can just use that one instead of calling source.ToList(). If you do it that way you'll have written a function that returns a computed value and modifies the contents of its argument; strongly consider not doing that.






              share|improve this answer









              $endgroup$




















                0












                $begingroup$

                All of dfhwze's points are spot-on, and the only thing I can think of to add to his type-signature is that if you're unfamiliar with all of the syntax he's using that's ok.
                (If you want to learn the stuff in question, search for "inheritance" (or "interface"), "generics", "extension methods", and possibly "generators" or "yield".)



                Regarding your actual algorithm:



                The big red flag that your current algorithm isn't good is that you have two nearly-identical loops. That they happen to be while loops is a small red flag, which you noticed indirectly when you noted that rnd.Next() can yield duplicates.



                The algorithm you probably want is to first shuffle your source list, and then take sequential runs from it as needed.
                Stack Exchange gives us usable implementations of both those steps. Only copy-paste them if you understand how they work and you want those exact methods lying around your code-base; most of the time it's better to re-write these things so that you're making the "details" decisions for yourself.





                • This answer gives us a nice implementation of The Fisher–Yates shuffle, which is efficient and appropriate.


                • This answer gives us tidy slicing. (What exactly happens if source.Count / (Double)size isn't an integer?)


                There are some details that probably matter, like whether or not the original order of the elements needs to be preserved, or what should happen if the source list isn't evenly divisible into the number of buckets in question.



                And once you've resolved all of that, since you asked about efficiency, we can return to dfhwze's function signature. Specifically, this IEnumerable<T> source is taken as an enumerable collection; the Fisher–Yates shuffle shuffles a list in place. It's very tempting to change the argument to this IList<T> source, so that if the calling context already has a list, we're can just use that one instead of calling source.ToList(). If you do it that way you'll have written a function that returns a computed value and modifies the contents of its argument; strongly consider not doing that.






                share|improve this answer









                $endgroup$


















                  0












                  0








                  0





                  $begingroup$

                  All of dfhwze's points are spot-on, and the only thing I can think of to add to his type-signature is that if you're unfamiliar with all of the syntax he's using that's ok.
                  (If you want to learn the stuff in question, search for "inheritance" (or "interface"), "generics", "extension methods", and possibly "generators" or "yield".)



                  Regarding your actual algorithm:



                  The big red flag that your current algorithm isn't good is that you have two nearly-identical loops. That they happen to be while loops is a small red flag, which you noticed indirectly when you noted that rnd.Next() can yield duplicates.



                  The algorithm you probably want is to first shuffle your source list, and then take sequential runs from it as needed.
                  Stack Exchange gives us usable implementations of both those steps. Only copy-paste them if you understand how they work and you want those exact methods lying around your code-base; most of the time it's better to re-write these things so that you're making the "details" decisions for yourself.





                  • This answer gives us a nice implementation of The Fisher–Yates shuffle, which is efficient and appropriate.


                  • This answer gives us tidy slicing. (What exactly happens if source.Count / (Double)size isn't an integer?)


                  There are some details that probably matter, like whether or not the original order of the elements needs to be preserved, or what should happen if the source list isn't evenly divisible into the number of buckets in question.



                  And once you've resolved all of that, since you asked about efficiency, we can return to dfhwze's function signature. Specifically, this IEnumerable<T> source is taken as an enumerable collection; the Fisher–Yates shuffle shuffles a list in place. It's very tempting to change the argument to this IList<T> source, so that if the calling context already has a list, we're can just use that one instead of calling source.ToList(). If you do it that way you'll have written a function that returns a computed value and modifies the contents of its argument; strongly consider not doing that.






                  share|improve this answer









                  $endgroup$



                  All of dfhwze's points are spot-on, and the only thing I can think of to add to his type-signature is that if you're unfamiliar with all of the syntax he's using that's ok.
                  (If you want to learn the stuff in question, search for "inheritance" (or "interface"), "generics", "extension methods", and possibly "generators" or "yield".)



                  Regarding your actual algorithm:



                  The big red flag that your current algorithm isn't good is that you have two nearly-identical loops. That they happen to be while loops is a small red flag, which you noticed indirectly when you noted that rnd.Next() can yield duplicates.



                  The algorithm you probably want is to first shuffle your source list, and then take sequential runs from it as needed.
                  Stack Exchange gives us usable implementations of both those steps. Only copy-paste them if you understand how they work and you want those exact methods lying around your code-base; most of the time it's better to re-write these things so that you're making the "details" decisions for yourself.





                  • This answer gives us a nice implementation of The Fisher–Yates shuffle, which is efficient and appropriate.


                  • This answer gives us tidy slicing. (What exactly happens if source.Count / (Double)size isn't an integer?)


                  There are some details that probably matter, like whether or not the original order of the elements needs to be preserved, or what should happen if the source list isn't evenly divisible into the number of buckets in question.



                  And once you've resolved all of that, since you asked about efficiency, we can return to dfhwze's function signature. Specifically, this IEnumerable<T> source is taken as an enumerable collection; the Fisher–Yates shuffle shuffles a list in place. It's very tempting to change the argument to this IList<T> source, so that if the calling context already has a list, we're can just use that one instead of calling source.ToList(). If you do it that way you'll have written a function that returns a computed value and modifies the contents of its argument; strongly consider not doing that.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 2 hours ago









                  ShapeOfMatterShapeOfMatter

                  41711 bronze badges




                  41711 bronze badges


























                      -2












                      $begingroup$

                      Below is a slightly improved algorithm of the problem.
                      This uses one while loop as opposed to two.



                      using System;
                      using System.Collections.Generic;

                      class Program
                      {
                      static List<String> AllPlayers = new List<String>();

                      static List<string> Team1 = new List<string>();
                      static List<string> Team2 = new List<string>();

                      static void Main(string[] args)
                      {

                      AllPlayers.Add("A1");
                      AllPlayers.Add("A2");
                      AllPlayers.Add("A3");
                      AllPlayers.Add("A4");
                      AllPlayers.Add("A5");
                      AllPlayers.Add("A6");


                      AllotPlayers();


                      Console.WriteLine("Team1");
                      foreach (var p in Team1)
                      Console.Write(" " + p + " ,");
                      Console.WriteLine();
                      Console.WriteLine("Team2");
                      foreach (var p in Team2)
                      Console.Write(" " + p + " ,");
                      }

                      static void AllotPlayers()
                      {
                      Random rnd = new Random();
                      int count = 0;
                      bool firstTeam = false;
                      string player = string.Empty;
                      int index = -1;
                      do
                      {
                      index = rnd.Next(AllPlayers.Count);
                      player = AllPlayers[index];
                      if (player == string.Empty) continue;

                      AllPlayers[index] = "";
                      if (firstTeam) Team2.Add(player);
                      else Team1.Add(player);
                      firstTeam = !firstTeam;
                      count++;
                      } while (count < AllPlayers.Count);
                      }
                      }





                      share|improve this answer









                      $endgroup$











                      • 3




                        $begingroup$
                        You've shown an alternative algorithm, but haven't reviewed the code at all. Please critique the code posted; I think that "This uses one while loop as opposed to two" is a little too brief to be a proper review. Thanks.
                        $endgroup$
                        – Toby Speight
                        5 hours ago










                      • $begingroup$
                        The point of code review is to provide suggestions to improve the posters code rather than provide alternate solutions. This answer only provides an alternate solution without an insightful observation. Alternate solutions may be deleted either by the community or the moderators.
                        $endgroup$
                        – pacmaninbw
                        5 hours ago


















                      -2












                      $begingroup$

                      Below is a slightly improved algorithm of the problem.
                      This uses one while loop as opposed to two.



                      using System;
                      using System.Collections.Generic;

                      class Program
                      {
                      static List<String> AllPlayers = new List<String>();

                      static List<string> Team1 = new List<string>();
                      static List<string> Team2 = new List<string>();

                      static void Main(string[] args)
                      {

                      AllPlayers.Add("A1");
                      AllPlayers.Add("A2");
                      AllPlayers.Add("A3");
                      AllPlayers.Add("A4");
                      AllPlayers.Add("A5");
                      AllPlayers.Add("A6");


                      AllotPlayers();


                      Console.WriteLine("Team1");
                      foreach (var p in Team1)
                      Console.Write(" " + p + " ,");
                      Console.WriteLine();
                      Console.WriteLine("Team2");
                      foreach (var p in Team2)
                      Console.Write(" " + p + " ,");
                      }

                      static void AllotPlayers()
                      {
                      Random rnd = new Random();
                      int count = 0;
                      bool firstTeam = false;
                      string player = string.Empty;
                      int index = -1;
                      do
                      {
                      index = rnd.Next(AllPlayers.Count);
                      player = AllPlayers[index];
                      if (player == string.Empty) continue;

                      AllPlayers[index] = "";
                      if (firstTeam) Team2.Add(player);
                      else Team1.Add(player);
                      firstTeam = !firstTeam;
                      count++;
                      } while (count < AllPlayers.Count);
                      }
                      }





                      share|improve this answer









                      $endgroup$











                      • 3




                        $begingroup$
                        You've shown an alternative algorithm, but haven't reviewed the code at all. Please critique the code posted; I think that "This uses one while loop as opposed to two" is a little too brief to be a proper review. Thanks.
                        $endgroup$
                        – Toby Speight
                        5 hours ago










                      • $begingroup$
                        The point of code review is to provide suggestions to improve the posters code rather than provide alternate solutions. This answer only provides an alternate solution without an insightful observation. Alternate solutions may be deleted either by the community or the moderators.
                        $endgroup$
                        – pacmaninbw
                        5 hours ago
















                      -2












                      -2








                      -2





                      $begingroup$

                      Below is a slightly improved algorithm of the problem.
                      This uses one while loop as opposed to two.



                      using System;
                      using System.Collections.Generic;

                      class Program
                      {
                      static List<String> AllPlayers = new List<String>();

                      static List<string> Team1 = new List<string>();
                      static List<string> Team2 = new List<string>();

                      static void Main(string[] args)
                      {

                      AllPlayers.Add("A1");
                      AllPlayers.Add("A2");
                      AllPlayers.Add("A3");
                      AllPlayers.Add("A4");
                      AllPlayers.Add("A5");
                      AllPlayers.Add("A6");


                      AllotPlayers();


                      Console.WriteLine("Team1");
                      foreach (var p in Team1)
                      Console.Write(" " + p + " ,");
                      Console.WriteLine();
                      Console.WriteLine("Team2");
                      foreach (var p in Team2)
                      Console.Write(" " + p + " ,");
                      }

                      static void AllotPlayers()
                      {
                      Random rnd = new Random();
                      int count = 0;
                      bool firstTeam = false;
                      string player = string.Empty;
                      int index = -1;
                      do
                      {
                      index = rnd.Next(AllPlayers.Count);
                      player = AllPlayers[index];
                      if (player == string.Empty) continue;

                      AllPlayers[index] = "";
                      if (firstTeam) Team2.Add(player);
                      else Team1.Add(player);
                      firstTeam = !firstTeam;
                      count++;
                      } while (count < AllPlayers.Count);
                      }
                      }





                      share|improve this answer









                      $endgroup$



                      Below is a slightly improved algorithm of the problem.
                      This uses one while loop as opposed to two.



                      using System;
                      using System.Collections.Generic;

                      class Program
                      {
                      static List<String> AllPlayers = new List<String>();

                      static List<string> Team1 = new List<string>();
                      static List<string> Team2 = new List<string>();

                      static void Main(string[] args)
                      {

                      AllPlayers.Add("A1");
                      AllPlayers.Add("A2");
                      AllPlayers.Add("A3");
                      AllPlayers.Add("A4");
                      AllPlayers.Add("A5");
                      AllPlayers.Add("A6");


                      AllotPlayers();


                      Console.WriteLine("Team1");
                      foreach (var p in Team1)
                      Console.Write(" " + p + " ,");
                      Console.WriteLine();
                      Console.WriteLine("Team2");
                      foreach (var p in Team2)
                      Console.Write(" " + p + " ,");
                      }

                      static void AllotPlayers()
                      {
                      Random rnd = new Random();
                      int count = 0;
                      bool firstTeam = false;
                      string player = string.Empty;
                      int index = -1;
                      do
                      {
                      index = rnd.Next(AllPlayers.Count);
                      player = AllPlayers[index];
                      if (player == string.Empty) continue;

                      AllPlayers[index] = "";
                      if (firstTeam) Team2.Add(player);
                      else Team1.Add(player);
                      firstTeam = !firstTeam;
                      count++;
                      } while (count < AllPlayers.Count);
                      }
                      }






                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered 5 hours ago









                      Up In AirUp In Air

                      274 bronze badges




                      274 bronze badges











                      • 3




                        $begingroup$
                        You've shown an alternative algorithm, but haven't reviewed the code at all. Please critique the code posted; I think that "This uses one while loop as opposed to two" is a little too brief to be a proper review. Thanks.
                        $endgroup$
                        – Toby Speight
                        5 hours ago










                      • $begingroup$
                        The point of code review is to provide suggestions to improve the posters code rather than provide alternate solutions. This answer only provides an alternate solution without an insightful observation. Alternate solutions may be deleted either by the community or the moderators.
                        $endgroup$
                        – pacmaninbw
                        5 hours ago
















                      • 3




                        $begingroup$
                        You've shown an alternative algorithm, but haven't reviewed the code at all. Please critique the code posted; I think that "This uses one while loop as opposed to two" is a little too brief to be a proper review. Thanks.
                        $endgroup$
                        – Toby Speight
                        5 hours ago










                      • $begingroup$
                        The point of code review is to provide suggestions to improve the posters code rather than provide alternate solutions. This answer only provides an alternate solution without an insightful observation. Alternate solutions may be deleted either by the community or the moderators.
                        $endgroup$
                        – pacmaninbw
                        5 hours ago










                      3




                      3




                      $begingroup$
                      You've shown an alternative algorithm, but haven't reviewed the code at all. Please critique the code posted; I think that "This uses one while loop as opposed to two" is a little too brief to be a proper review. Thanks.
                      $endgroup$
                      – Toby Speight
                      5 hours ago




                      $begingroup$
                      You've shown an alternative algorithm, but haven't reviewed the code at all. Please critique the code posted; I think that "This uses one while loop as opposed to two" is a little too brief to be a proper review. Thanks.
                      $endgroup$
                      – Toby Speight
                      5 hours ago












                      $begingroup$
                      The point of code review is to provide suggestions to improve the posters code rather than provide alternate solutions. This answer only provides an alternate solution without an insightful observation. Alternate solutions may be deleted either by the community or the moderators.
                      $endgroup$
                      – pacmaninbw
                      5 hours ago






                      $begingroup$
                      The point of code review is to provide suggestions to improve the posters code rather than provide alternate solutions. This answer only provides an alternate solution without an insightful observation. Alternate solutions may be deleted either by the community or the moderators.
                      $endgroup$
                      – pacmaninbw
                      5 hours ago












                      esilik is a new contributor. Be nice, and check out our Code of Conduct.










                      draft saved

                      draft discarded


















                      esilik is a new contributor. Be nice, and check out our Code of Conduct.













                      esilik is a new contributor. Be nice, and check out our Code of Conduct.












                      esilik is a new contributor. Be nice, and check out our Code of Conduct.
















                      Thanks for contributing an answer to Code Review Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      Use MathJax to format equations. MathJax reference.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f225287%2fcreate-two-random-teams-from-a-list-of-players%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Taj Mahal Inhaltsverzeichnis Aufbau | Geschichte | 350-Jahr-Feier | Heutige Bedeutung | Siehe auch |...

                      Baia Sprie Cuprins Etimologie | Istorie | Demografie | Politică și administrație | Arii naturale...

                      Nicolae Petrescu-Găină Cuprins Biografie | Opera | In memoriam | Varia | Controverse, incertitudini...