C# 从任意数量的列中计算单词的组合
C# calculate combinations of words from an arbitrary number of columns
有很多针对单个数组或数组向量的组合解决方案,您需要各种可能的排列,但我需要稍微不同的解决方案。我试着把碎片拼在一起,但再也见不到树木了。
我需要一个解决方案,它将采用一个 csv 文件,该文件包含最多 50 列和每列任意数量的单词行。每列的行数可以不同。
我需要做的是获取此输入并依次遍历每一列,选择一个词来创建每个可能的行组合,跳过任何 row/column 为空的行。嵌套循环会对预设数量的列执行此操作,但随着列的更改,这是一个问题。编程相当新。希望我缺少一个相当简单的逻辑概念。
例如:
输入:
熊、爪、甜甜圈
鸡肉,沙拉,
金枪鱼,沙拉
输出:
熊、爪、甜甜圈
熊,沙拉,甜甜圈
熊,沙拉
鸡、爪、甜甜圈
鸡肉、沙拉、甜甜圈
鸡爪
鸡肉、沙拉
鸡肉、沙拉、甜甜圈
...
金枪鱼、爪、沙拉
金枪鱼沙拉
等等
我不确定我是否正确回答了您的问题。您似乎缺少一些解决方案。
public static IEnumerable<string[]> GetAllCombinations(string[,] input, Stack<string> current = null, int currentCol = 0)
{
if (current == null) current = new Stack<string>();
var rows = input.GetLength(0);
var cols = input.GetLength(1);
for (var row = 0; row < rows; row++)
{
if (input[row, currentCol] == null) continue;
current.Push(input[row, currentCol]);
if (currentCol == cols - 1)
{
var result = current.ToArray();
Array.Reverse(result);
yield return result;
}
else
{
var subResults = GetAllCombinations(input, current, currentCol + 1);
foreach (var subResult in subResults)
yield return subResult;
}
current.Pop();
}
}
static void Main()
{
var input = new[,]
{
{"bear", "claw", "donut"},
{"chicken", "salad", null},
{"tuna", null, "salad"}
};
foreach (var comb in GetAllCombinations(input))
Console.WriteLine(string.Join(",", comb));
}
和输出:
bear,claw,donut
bear,claw,salad
bear,salad,donut
bear,salad,salad
chicken,claw,donut
chicken,claw,salad
chicken,salad,donut
chicken,salad,salad
tuna,claw,donut
tuna,claw,salad
tuna,salad,donut
tuna,salad,salad
我在 , but shortly after, the requirements became unclear, so I refrained from posting it. Now that they are clear, here is an alternative that uses IEnumerable
的同时写了一个答案。它也不需要 Array.Reverse()
每个答案。
原始答案文本
你会想递归地解决这个问题。
下面的代码假定您已经将 CSV 解析为 IEnumerable
的 IEnumerable
部分。
static void Main()
{
var wordLists = new List<string[]>()
{
new string[] { "bear", "chicken", "tuna" },
new string[] { "claw", null, "salad" },
null,
new string[] { "donut", "salad", null },
};
foreach (var result in AllPermutations(wordLists))
{
System.Console.WriteLine(string.Join(",", result));
}
}
// our recursive function.
private static IEnumerable<IEnumerable<string>> AllPermutations(IEnumerable<IEnumerable<string>> wordLists, int index = 0, List<string> current = null)
{
if (current == null)
{
current = new List<string>();
}
if (index == wordLists.Count())
{ // the end condtion. it is reached when we are past the last list
yield return current;
}
else
{ // if we are not at the end yet, loop through the entire list
// of words, appending each one, then recursively combining
// the other lists, and finally removing the word again.
var wordList = wordLists.ElementAt(index);
if (wordList != null)
{
foreach (var word in wordList)
{
if (word == null) continue;
current.Add(word);
foreach (var result in AllPermutations(wordLists, index + 1, current))
{
yield return result;
}
current.RemoveAt(current.Count - 1);
}
}
else
{
foreach (var result in AllPermutations(wordLists, index + 1, current))
{
yield return result;
}
}
}
}
请注意,对于 50 列,可能会有 很多 组合非常快。
有很多针对单个数组或数组向量的组合解决方案,您需要各种可能的排列,但我需要稍微不同的解决方案。我试着把碎片拼在一起,但再也见不到树木了。
我需要一个解决方案,它将采用一个 csv 文件,该文件包含最多 50 列和每列任意数量的单词行。每列的行数可以不同。
我需要做的是获取此输入并依次遍历每一列,选择一个词来创建每个可能的行组合,跳过任何 row/column 为空的行。嵌套循环会对预设数量的列执行此操作,但随着列的更改,这是一个问题。编程相当新。希望我缺少一个相当简单的逻辑概念。
例如:
输入:
熊、爪、甜甜圈
鸡肉,沙拉,
金枪鱼,沙拉
输出:
熊、爪、甜甜圈
熊,沙拉,甜甜圈
熊,沙拉
鸡、爪、甜甜圈
鸡肉、沙拉、甜甜圈
鸡爪
鸡肉、沙拉
鸡肉、沙拉、甜甜圈
...
金枪鱼、爪、沙拉
金枪鱼沙拉
等等
我不确定我是否正确回答了您的问题。您似乎缺少一些解决方案。
public static IEnumerable<string[]> GetAllCombinations(string[,] input, Stack<string> current = null, int currentCol = 0)
{
if (current == null) current = new Stack<string>();
var rows = input.GetLength(0);
var cols = input.GetLength(1);
for (var row = 0; row < rows; row++)
{
if (input[row, currentCol] == null) continue;
current.Push(input[row, currentCol]);
if (currentCol == cols - 1)
{
var result = current.ToArray();
Array.Reverse(result);
yield return result;
}
else
{
var subResults = GetAllCombinations(input, current, currentCol + 1);
foreach (var subResult in subResults)
yield return subResult;
}
current.Pop();
}
}
static void Main()
{
var input = new[,]
{
{"bear", "claw", "donut"},
{"chicken", "salad", null},
{"tuna", null, "salad"}
};
foreach (var comb in GetAllCombinations(input))
Console.WriteLine(string.Join(",", comb));
}
和输出:
bear,claw,donut
bear,claw,salad
bear,salad,donut
bear,salad,salad
chicken,claw,donut
chicken,claw,salad
chicken,salad,donut
chicken,salad,salad
tuna,claw,donut
tuna,claw,salad
tuna,salad,donut
tuna,salad,salad
我在 IEnumerable
的同时写了一个答案。它也不需要 Array.Reverse()
每个答案。
原始答案文本
你会想递归地解决这个问题。
下面的代码假定您已经将 CSV 解析为 IEnumerable
的 IEnumerable
部分。
static void Main()
{
var wordLists = new List<string[]>()
{
new string[] { "bear", "chicken", "tuna" },
new string[] { "claw", null, "salad" },
null,
new string[] { "donut", "salad", null },
};
foreach (var result in AllPermutations(wordLists))
{
System.Console.WriteLine(string.Join(",", result));
}
}
// our recursive function.
private static IEnumerable<IEnumerable<string>> AllPermutations(IEnumerable<IEnumerable<string>> wordLists, int index = 0, List<string> current = null)
{
if (current == null)
{
current = new List<string>();
}
if (index == wordLists.Count())
{ // the end condtion. it is reached when we are past the last list
yield return current;
}
else
{ // if we are not at the end yet, loop through the entire list
// of words, appending each one, then recursively combining
// the other lists, and finally removing the word again.
var wordList = wordLists.ElementAt(index);
if (wordList != null)
{
foreach (var word in wordList)
{
if (word == null) continue;
current.Add(word);
foreach (var result in AllPermutations(wordLists, index + 1, current))
{
yield return result;
}
current.RemoveAt(current.Count - 1);
}
}
else
{
foreach (var result in AllPermutations(wordLists, index + 1, current))
{
yield return result;
}
}
}
}
请注意,对于 50 列,可能会有 很多 组合非常快。