如何在没有下一个和上一个列表重复的情况下洗牌 List<List<string>>

How to shuffle List<List<string>> without next and previous list having duplicates

所以我有几个列表

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);

如果列表是 "apples",它包含的唯一值是 "apples",但列表中的元素数量不同。我怎样才能打乱这个,这样最终的结果就是这样的。

orange_small
apple_small
orange_big
grape_medium
apple_big
grape_small
orange_medium
apple_medium
grape_big

或下一个和上一个列表不是来自同一个水果的任何其他可行组合?

每次列表包含不同的水果和里面的水果数量。因此,如果我们将列表视为一个数组。

[A1,A2,A3,B1,B2,B3,C1,C2,C3] shuffle 可以是任何类型,无需重复下一个和上一个类型。 [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)];
        }
    }

结果如下:

foreach (var list in ShuffleList(fruits))
{
     Console.WriteLine($"{list.First()}: {list.Count}");
}

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

如果仅使用所有 "apples" 和一个 "orange",结果将重复:

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