C# 如何洗牌列表<;列表<;字符串>&燃气轮机;没有下一个和上一个列表具有重复项

C# 如何洗牌列表<;列表<;字符串>&燃气轮机;没有下一个和上一个列表具有重复项,c#,shuffle,C#,Shuffle,所以我有两张单子 List<List<string>> fruits = new List<List<string>>(); List<string> apple_small = new List<string>(); apple_small.Add("apple"); apple_small.Add("apple"); List<string> apple_medium = new List<strin

所以我有两张单子

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

List<string> apple_small = new List<string>();
apple_small.Add("apple");
apple_small.Add("apple");
List<string> apple_medium = new List<string>();
apple_medium.Add("apple");
apple_medium.Add("apple");
apple_medium.Add("apple");
List<string> apple_big = new List<string>();
apple_big.Add("apple");
apple_big.Add("apple");
apple_big.Add("apple");
apple_big.Add("apple");
List<string> orange_small = new List<string>();
orange_small.Add("orange");
orange_small.Add("orange");
List<string> orange_medium = new List<string>();
orange_medium.Add("orange");
orange_medium.Add("orange");
orange_medium.Add("orange");
List<string> orange_big = new List<string>();
orange_big.Add("orange");
orange_big.Add("orange");
orange_big.Add("orange");
orange_big.Add("orange");
List<string> grape_small = new List<string>();
grape_small.Add("grape");
grape_small.Add("grape");
List<string> grape_medium = new List<string>();
grape_medium.Add("grape");
grape_medium.Add("grape");
grape_medium.Add("grape");
List<string> grape_big = new List<string>();
grape_big.Add("grape");
grape_big.Add("grape");
grape_big.Add("grape");
grape_big.Add("grape");

fruits.Add(apple_small);
fruits.Add(apple_medium);
fruits.Add(apple_big);

fruits.Add(orange_small);
fruits.Add(orange_medium);
fruits.Add(orange_big);

fruits.Add(grape_small);
fruits.Add(grape_medium);
fruits.Add(grape_big);
或者任何其他可行的组合,其中下一个和前一个列表不是来自同一个水果

每次列表中都包含不同的水果和水果数量。如果我们把列表看作一个数组

[A1、A2、A3、B1、B2、B3、C1、C2、C3]洗牌可以是任何类型,而无需重复下一个和上一个类型。[A1,B1,C3,B2,C2,A2,C1,B1…]

例如,在某些情况下,值不允许以每个符号都不会重复的方式对组合进行洗牌

[A1,A2,A3,B1]如果我有这样的列表,它应该是

[A1,B1,A2,B1,A3]如果没有更多的随机播放选项,它应该能够重用列表

像这样的

    public static List<List<string>> ShuffleList(List<List<string>> fruits)
    {
        var random = new Random();
        var copy = fruits.ToList();
        var shuffle = new List<List<string>>();
        List<string> previous = null;
        while (true)
        {
            var next = GetNext();
            copy.Remove(next);
            shuffle.Add(next);
            previous = next;

            if(!copy.Any()) break;
        }

        return shuffle;

        List<string> GetNext()
        {
            if (previous is null)
            {
                return copy[random.Next(copy.Count)];
            }

            var otherFruits = copy.Where(list => list.Any(f => f != previous[0])).ToList();
            if (otherFruits.Count == 0)
            {
                // start use duplicates if no more unique values
                otherFruits = fruits.Where(list => list.Any(f => f != previous[0])).ToList();
            }
            return otherFruits[random.Next(otherFruits.Count)];
        }
    }
如果只使用所有“苹果”和一个“橙色”,结果将具有重复项:

apple: 4
orange: 2
apple: 2
orange: 2
apple: 3
像这样的

    public static List<List<string>> ShuffleList(List<List<string>> fruits)
    {
        var random = new Random();
        var copy = fruits.ToList();
        var shuffle = new List<List<string>>();
        List<string> previous = null;
        while (true)
        {
            var next = GetNext();
            copy.Remove(next);
            shuffle.Add(next);
            previous = next;

            if(!copy.Any()) break;
        }

        return shuffle;

        List<string> GetNext()
        {
            if (previous is null)
            {
                return copy[random.Next(copy.Count)];
            }

            var otherFruits = copy.Where(list => list.Any(f => f != previous[0])).ToList();
            if (otherFruits.Count == 0)
            {
                // start use duplicates if no more unique values
                otherFruits = fruits.Where(list => list.Any(f => f != previous[0])).ToList();
            }
            return otherFruits[random.Next(otherFruits.Count)];
        }
    }
如果只使用所有“苹果”和一个“橙色”,结果将具有重复项:

apple: 4
orange: 2
apple: 2
orange: 2
apple: 3

在内部列表中有多个苹果的目的是什么?每个“苹果列表”中的苹果数是不同的。哦,我明白了。我将编辑代码,它不准确,但每个列表的编号应该不同。让我重新表述一下:在列表中有一个列表会使事情变得更复杂,使解决方案更复杂(我们必须获取第一个项目,并相信所有其他项目都是相同的)。如果所有的值都相同,那么嵌套列表的目的是什么?我的意思是什么可以阻止您使用
list
其中
Fruit
包含水果名称和计数?有什么原因不能这样做吗?没有Fruit类的唯一原因是没有更改当前程序的主逻辑,因为它输出代码中所示的列表。但是我想如果没有其他的事情发生,它是可以改变的。在内部列表中有多个苹果的目的是什么?每个“苹果列表”中的苹果数量是不同的。哦,我明白了。我将编辑代码,它不准确,但每个列表的编号应该不同。让我重新表述一下:在列表中有一个列表会使事情变得更复杂,使解决方案更复杂(我们必须获取第一个项目,并相信所有其他项目都是相同的)。如果所有的值都相同,那么嵌套列表的目的是什么?我的意思是什么可以阻止您使用
list
其中
Fruit
包含水果名称和计数?有什么原因不能这样做吗?没有Fruit类的唯一原因是没有更改当前程序的主逻辑,因为它输出代码中所示的列表。但我想如果没有其他事情发生,它是可以改变的。是的,谢谢你,它像我想要的那样洗牌。我还没有完全测试它,如果没有足够的值来洗牌的话,它是否会正确地shuflfe,但我可以从那里开始工作。非常感谢。我还没有测试过这个,但是如果你最后剩下3个“苹果”列表,会发生什么呢?如果只剩下3个“苹果”列表,就编辑它开始使用重复的列表。是的,谢谢你,它会像我想要的那样洗牌。我还没有完全测试它,如果没有足够的值来洗牌的话,它是否会正确地shuflfe,但我可以从那里开始工作。非常感谢。我还没有测试过这个,但是如果你最后只剩下3个“苹果”列表,会发生什么呢?如果只剩下3个“苹果”列表,就编辑它开始使用重复的列表。