用所有组合填充数组
本文关键字:填充 数组 组合 | 更新日期: 2023-09-27 18:02:17
给定一个枚举,我想知道如何填充一个锯齿数组,以便每个内部数组包含枚举值的组合(枚举中有7个值,内部数组中有6个槽,允许重复),外部数组包含每个可能的组合(不是排列;红红红红橙和红红红红红橙红是同一个元素)。
多维数组也可以,尽管锯齿数组似乎更适用于现实世界的问题。我只是不知道如何编写填充它的循环。
语言是c#。我希望以一种从"最高"到"最低"值排序结果的方式填充它(从Red Red Red Red Red Red Red开始,然后是Red Red Red Red Red Orange,等等)。这是enum:
public enum OrderedColors
{
Colorless,
Purple,
Blue,
Green,
Yellow,
Orange,
Red
}
您可以使用简单的递归函数来实现它的可伸缩性。它接收要组合的项目数组,要从数组中选择的项目数量以及要从数组中选择项目的起始索引(默认为0)。它递归地在每个允许的起始位置选择第一个项目,并将所有其他元素的组合附加到项目数组的右侧。
public static IEnumerable<T[]> BuildCombinations<T>(T[] items, int itemsCountInCombination, int startIndex = 0)
{
if (itemsCountInCombination == 0)
{
yield return new T[0];
yield break;
}
for (int i = startIndex; i < items.Length; i++)
{
foreach (var combination in BuildCombinations(items, itemsCountInCombination - 1, i))
{
var c = new T[itemsCountInCombination];
c[0] = items[i];
Array.Copy(combination, 0, c, 1, combination.Length);
yield return c;
}
}
}
private static void Main(string[] args)
{
foreach (var c in BuildCombinations(Enum.GetValues(typeof (OrderedColors)).Cast<OrderedColors>().Reverse().ToArray(), 6))
{
foreach (var color in c)
{
Console.Write(color);
Console.Write(" ");
}
Console.WriteLine();
}
}
它在0.44 ms内生成预期的924个组合,其中重复7个元素中的6个。这可能不是最好的性能,而且它使用的内存比可能的要多,但它的实现非常简单,并且对于这样数量的元素来说足够有效。
我发现这个问题很有趣,并继续研究解决方案…给你……
像这样使用代码…
var example = new[] {
OrderedColors.Red, OrderedColors.Orange, OrderedColors.Yellow,
OrderedColors.Green, OrderedColors.Blue, OrderedColors.Purple,
OrderedColors.Colorless };
var combinations = example.CombinationsWithRepetition(6);
按预期产生924个结果,并且不做任何不必要的计算或复制。以下是实际的方法。
public static IEnumerable<IList<T>> CombinationsWithRepetition<T>
(this IEnumerable<T> input, int take) where T : new()
{
var items = input.ToList();
return CombinationsWithRepetition(items, null, take, 0, 0);
}
private static IEnumerable<IList<T>> CombinationsWithRepetition<T>
(List<T> allItems, IList<T> thisSequence, int maxLength,
int currentLength, int currentIndex)
{
if (maxLength == 0)
yield return new List<T>();
for (var index = currentIndex; index < allItems.Count; index++)
{
var nextSequence = thisSequence == null ? new List<T>() :
thisSequence.ToList();
nextSequence.Add(allItems[index]);
if (currentLength + 1 == maxLength)
{
yield return nextSequence;
}
else
{
foreach (var sequence in CombinationsWithRepetition(allItems,
nextSequence, maxLength, currentLength + 1, index))
{
yield return sequence;
}
}
}
}
享受吧!
using LINQ:
OrderedColors[] colors = (OrderedColors[])Enum.GetValues(typeof(OrderedColors));
OrderedColors[][] matrix = (
from a in colors
from b in colors
from c in colors
from d in colors
from e in colors
from f in colors
select new [] {a,b,c,d,e,f}
).ToArray();
如果你想生成任意长度的组合,那么你需要更复杂的东西。
编辑:您可以通过在每个from后面添加where子句来修复它:
OrderedColors[][] matrix = (
from a in colors
from b in colors
where a<=b
from c in colors
where b<=c
from d in colors
where c<=d
from e in colors
where d<=e
from f in colors
where e<=f
select new [] {a,b,c,d,e,f}
).ToArray();