Создайте два случайных списка из одного списка - PullRequest
4 голосов
/ 26 сентября 2019

Я хочу взять список строк с примерно 12 объектами и разделить его на два списка строк, но полностью случайным образом.

Пример списка:

Список 1:

EXAMPLE 1
EXAMPLE 2
EXAMPLE 3
EXAMPLE 4
EXAMPLE 5
EXAMPLE 6
EXAMPLE 7
EXAMPLE 8

Примените здесь некоторую логику ...

Результат дает мне два списка: Список 1:

EXAMPLE 5
EXAMPLE 6
EXAMPLE 1
EXAMPLE 8

Список 2:

EXAMPLE 2
EXAMPLE 3
EXAMPLE 4
EXAMPLE 7

IЯ новичок в C # MVC, поэтому я нашел несколько ответов по стеку, но никто не смог ответить на мой вопрос.

Редактировать: То, что я пробовал до сих пор, дает мне одного случайного члена команды,Теперь я хочу расширить это и создать два списка, как упомянуто выше.

  [HttpPost]
    public ActionResult Result(Models.TeamGenerator model)
    {
        var FormNames = model.Names;

        string[] lines = FormNames.Split(
            new[] { Environment.NewLine },
            StringSplitOptions.None);

        List<string> listOfLines = new List<string>();

        foreach (var i in lines)
        {
            listOfLines.Add(i);
        }
        string[] result1 = listOfLines.Where(item => item != string.Empty).ToArray();

        Random genRandoms = new Random();
        int aRandomTeam = genRandoms.Next(listOfLines.Count);

        string currName = listOfLines[aRandomTeam];

        return View();
    }

Ответы [ 5 ]

2 голосов
/ 26 сентября 2019
  1. Создайте массив bool того же размера, что и список строк.
  2. Заполните одну половину массива bools true, а другую половину false.
  3. Перемешать массив bools.
  4. Перебрать список строк.Для каждого элемента, если соответствующий элемент в массиве bool равен true, включите этот элемент в первый список;в противном случае включите его во второй список.

Этот подход сохраняет элементы в том же порядке, в котором они были в исходном массиве, если это важно.(Если нет, просто перетасуйте весь массив строк и возьмите первую половину и вторую половину.)

Пример кода:

using System;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        public static void Main()
        {
            var strings = Enumerable.Range(1, 20).Select(i => i.ToString()).ToList();

            var rng = new Random();
            int n = strings.Count;

            var include = // Create array of bools where half the elements are true and half are false
                Enumerable.Repeat(true, n/2) // First half is true
                .Concat(Enumerable.Repeat(false, n-n/2)) // Second half is false
                .OrderBy(_ => rng.Next()) // Shuffle
                .ToArray(); 

            var list1 = strings.Where((s, i) =>  include[i]).ToList(); // Take elements where `include[index]` is true
            var list2 = strings.Where((s, i) => !include[i]).ToList(); // Take elements where `include[index]` is false

            Console.WriteLine(string.Join(", ", list1));
            Console.WriteLine(string.Join(", ", list2));
        }
    }
}

Вот совершенно другой подход, который используетмодифицированная версия стандартного алгоритма для выбора K элементов из N элементов (в данном случае K = N / 2):

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        public static void Main()
        {
            var strings = Enumerable.Range(1, 20).Select(n => n.ToString()).ToList();

            var list1 = new List<string>();
            var list2 = new List<string>();

            var rng       = new Random();
            int available = strings.Count;
            int remaining = available / 2;

            foreach (var s in strings)
            {
                if (rng.NextDouble() < remaining / (double) available)
                {
                    list1.Add(s);
                    --remaining;
                }
                else
                {
                    list2.Add(s);
                }

                --available;
            }

            Console.WriteLine(string.Join(", ", list1));
            Console.WriteLine(string.Join(", ", list2));
        }
    }
}

Этот подход намного более эффективен, чем мое первое решение, но так как ваш списоквсего около 12 предметов, это вряд ли важно для вашей проблемы.

2 голосов
/ 26 сентября 2019

Сначала попробуйте перетасовать список с помощью функции Random

static class MyExtensions
{
    private static Random rng = new Random();
    public static void Shuffle<T>(this IList<T> list)
    {
        int n = list.Count;
        while (n > 1)
        {
            n--;
            int k = rng.Next(n + 1);
            T value = list[k];
            list[k] = list[n];
            list[n] = value;
        }
    }
}

, а затем разбить список на два с помощью Linq

    static void Main(String[] args)
    {
        List<string> examples = new List<string>();
        for(int i=1;i<=12;i++)
        {
            examples.Add($"Example {i}");
        }

        examples.Shuffle();

        var firstlist = examples.Take(examples.ToArray().Length / 2).ToArray();
        Console.WriteLine(String.Join(", ", firstlist));
        var secondlist = examples.Skip(examples.ToArray().Length / 2).ToArray();
        Console.WriteLine(String.Join(", ", secondlist));
        Console.ReadLine();
    }

результат выглядит следующим образом

Example 6, Example 8, Example 3, Example 9, Example 5, Example 2
Example 10, Example 11, Example 4, Example 7, Example 12, Example 1
1 голос
/ 26 сентября 2019

Итак, я написал пример в консольном приложении, но концепция работает точно так же ... Смотрите комментарии в блоке кода ниже

Пример списка

var fullList = new List<string>()
{
    "ITEM 01", "ITEM 02", "ITEM 03", "ITEM 04", "ITEM 05", "ITEM 06",
    "ITEM 07", "ITEM 08", "ITEM 09", "ITEM 10", "ITEM 11", "ITEM 12"
};

Инициализация двух списков для разделения значений

var list1 = new List<string>();
var list2 = new List<string>();

Создание двух случайных списков

// Initialize one Random object to use throughout the loop
var random = new Random();

// Note: Start at count and count down because we will alter the count of the list
//       so counting up is going to mess up. Ex: Count = 4, Remove 1 (Count = 3), Loop won't go to 4
for(int i = fullList.Count; i > 0; i--)
{
    // Pull random index
    var randomIndex = random.Next(fullList.Count);

    // Pull item at random index
    var listItem = fullList[randomIndex];

    // If i is even, put it in list 1, else put it in list 2. 
    // You could do whatever you need to choose a list to put it
    if (i % 2 == 0)
        list1.Add(listItem);
    else
        list2.Add(listItem);

    // Remove random item from the full list so it doesn't get chosen again
    fullList.RemoveAt(randomIndex);
}

Результаты

Console.WriteLine("LIST 1");
Console.WriteLine(string.Join(Environment.NewLine, list1));

Console.WriteLine();
Console.WriteLine("LIST 2");
Console.WriteLine(string.Join(Environment.NewLine, list2));

-----------------------
LIST 1
ITEM 05
ITEM 04
ITEM 12
ITEM 11
ITEM 08
ITEM 01

LIST 2
ITEM 02
ITEM 03
ITEM 09
ITEM 06
ITEM 10
ITEM 07
1 голос
/ 26 сентября 2019

В настоящее время вы генерируете только одно случайное число и получаете одно значение.Что вам нужно сделать, это поместить его в цикл, который запускается вдвое меньше, чем количество элементов в списке.

var genRandoms = new Random();
var numberRequired = listOfLines.Count/2;
var output = new List<string>();
for (var i=0; i<numberRequired; i++)
{
    var aRandomTeam = genRandoms.Next(listOfLines.Count);
    output.Add(listOfLines[aRandomTeam]);
    listOfLines.RemoveAt(aRandomTeam);
}

Кроме того, этот бит в начале:

string[] lines = FormNames.Split(
        new[] { Environment.NewLine },
        StringSplitOptions.None);

    List<string> listOfLines = new List<string>();

    foreach (var i in lines)
    {
        listOfLines.Add(i);
    }
    string[] result1 = listOfLines.Where(item => item != string.Empty).ToArray();

Можно переписать как:

var listOfLines = FormNames.Split(
        new[] { Environment.NewLine },
        StringSplitOptions.RemoveEmptyEntries).ToList();

Удаление пустых элементов как части разделения и использование встроенного метода для преобразования его в список.

0 голосов
/ 26 сентября 2019

Вот простое решение , которое соответствует тому, как вы пытались решить проблему.

Основная логика следующая:

while there are still items in the master list:
  choose a random number [0,list.count) as the current target index
  choose a random number [0,1] as the current target list to add to
  add the item chosen randomly to the randomly selected list
  remove the item chosen from the master list

Вот код:

        var random = new Random();

        var list = new List<string> { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"  };

        var newList1 = new List<string>();
        var newList2 = new List<string>();
        while(list.Count > 0)
        {
            //choose the index randomly
            int index = random.Next(list.Count);

            //get the item at the randomly chosen index
            string curItem = list[index];

            //choose the list randomly(1==newList1, 2==newList2)
            int listChoice = random.Next(2);

            //Add the item to the correct list
            if(listChoice == 1)
            {
                newList1.Add(curItem);
            }
            else
            {
                newList2.Add(curItem);
            }
            //finally, remove the element from the string
            list.RemoveAt(index);
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...