Пока список не пуст, удалить случайный элемент из списка в бесконечном цикле - PullRequest
0 голосов
/ 03 октября 2019

Я работаю над простым shuffle сценарием . У меня есть общий метод, который принимает в качестве входных данных List<T> и возвращает List<T>. Возвращенное List должно быть перемешано . Однако код застрял в бесконечном цикле , и я не уверен, почему .

Вот мой код:

private List<T> Shuffle<T>(List<T> p)
{
    List<T> result = new List<T>();
    int idx = 0;

    while (p.Count > 0)
    {
        idx = Random.Range(0, p.Count);

        print(idx);
        result.Add(p[idx]);
        p.Remove(p[idx]);
    }

    print("Shuffled");
    return result;
}

Я ожидаю, что код будет работать, поскольку p.Count продолжает уменьшаться . Однако, это застревает . Вот альтернатива выполненному мною циклу while, который работает, но выглядит немного неряшливо:

for (int i = 0; i < p.Count; i++)
{
    idx = Random.Range(0, p.Count);
    print(idx);

    result.Add(p[idx]);
    p.Remove(p[idx]);
}

Это скорее вопрос «почему» , чем проблема, но явсе еще надеюсь, что ты сможешь мне помочь. Заранее спасибо!

1 Ответ

3 голосов
/ 03 октября 2019

Самая первая строка

List<T> result = p;

- это проблема . Обратите внимание, что result и p имеют одинаковую одинаковую ссылку , поэтому

result.Add(p[idx]);

добавляет к result и p , а также , p.Count > 0 всегда удерживает (превращая while (p.Count > 0) в бесконечный цикл ). Должно быть

private List<T> Shuffle<T>(List<T> p)
{
    List<T> result = new List<T>(); // result and p are different lists now

    while (p.Count > 0)
    {
        idx = Random.Range(0, p.Count);

        print(idx);
        result.Add(p[idx]);  // Now we Add to result only, and Remove from p
        p.RemoveAt(idx);     // <- I suggest removing at index
    }

    print("Shuffled");
    return result;
}
...