好的,所以希望我能够足够详细地解释一下这个人能够帮助我..我正在用C#编写一个程序,它应该采用一个文本文件并替换特定的文本,这些文本恰好是文件,并为给定文件名的每个组合打印一个新的文本文件。更改文件名文本的特定位置有自己的一组可能的文件名,列为下面描述的数组。无论每个位置可用的文件名数量以及文件名的总位置数,该程序都应该运行。如果你真的想让它变得很棒,可以稍微优化它,因为知道在任何单个文本文件中都不应该复制任何文件名。
text
是一系列行,构成了整个文件的基础。
lineNum
包含文件名条目的行位置数组。
previousFiles
是以前使用的文件名数组,从文件中已有的文件名开始。
files
是一个可能的文件名的锯齿状二维数组,其中files[1]
是第二个位置的所有可能文件名的数组
下面是一个示例,说明如何使用3个单独的文件名位置,第一个给出3个可能的文件名,第二个给出8个可能的文件名,第三个给出3个可能的文件名。
哦,假设buildNewFile有效。
int iterator = 0;
for (int a = 0; a < 3; a++)
{
for (int b = 0; b < 8; b++)
{
for (int c = 0; c < 3; c++)
{
iterator++;
text[lineNums[0]] = text[lineNums[0]].Replace(previousFiles[0], files[0][a]);
text[lineNums[1]] = text[lineNums[1]].Replace(previousFiles[0], files[0][a]);
text[lineNums[2]] = text[lineNums[2]].Replace(previousFiles[1], files[1][b]);
text[lineNums[3]] = text[lineNums[3]].Replace(previousFiles[1], files[1][b]);
text[lineNums[4]] = text[lineNums[4]].Replace(previousFiles[2], files[2][c]);
text[lineNums[5]] = text[lineNums[5]].Replace(previousFiles[2], files[2][c]);
previousFiles = new string[] { files[0][a], files[1][b], files[2][c] };
buildNewFile(text, Info.baseFolder + "networks\\" + Info.dsnFilename + iterator + ".dsn");
}
}
}
如果你们可以帮助我,非常感谢你,我无法弄清楚如何以递归或其他方式做到这一点。如果您有任何问题,我会回答并编辑,以反映这一点。
答案 0 :(得分:1)
我花了一点时间才弄清楚你真正想做什么。这个问题可以在没有递归的情况下解决,诀窍是查看你拥有的数据并将其变为更有用的格式。
您的“文件”数组是最不方便的数组。诀窍是将数据转换为可用的排列。为此,我建议利用yield并使用返回IEnumerable的方法。它的代码在这里:
public IEnumerable<string[]> GenerateFileNameStream(string[][] files)
{
int[] current_indices = new int[files.Length];
current_indices.Initialize();
List<string> file_names = new List<string>();
while (current_indices[0] < files[0].Length)
{
file_names.Clear();
for (var index_index = 0; index_index < current_indices.Length; index_index++)
{
file_names.Add(files[index_index][current_indices[index_index]]);
}
yield return file_names.ToArray();
// increment the indices, trickle down as needed
for (var check_index = 0; check_index < current_indices.Length; check_index++)
{
current_indices[check_index]++;
// if the index hasn't rolled over, we're done here
if (current_indices[check_index] < files[check_index].Length) break;
// if the last location rolls over, then we are totally done
if (check_index == current_indices.Length - 1) yield break;
// reset this index, increment the next one in the next iteration
current_indices[check_index] = 0;
}
}
}
基本上,它会跟踪files
2D数组的每一行的当前索引,并返回每个当前索引处的文件名。然后它递增第一个索引。如果第一个索引翻转,则它将重置为0并改为增加下一个索引。这样我们就可以遍历文件名的每个排列。
现在,看一下lineNum
和files
之间的关系,我假设文件中的每个位置都被复制到两行。其余的代码在这里:
public void MakeItWork(string[][] files, int[] lineNum, string[] text, string[] previousFiles)
{
var iterator = 0;
var filenames = GenerateFileNameStream(files);
// work a copy of the text, assume the "previousFiles" are in this text
var text_copy = new string[text.Length];
foreach (var filenameset in filenames)
{
iterator++;
Array.Copy(text, text_copy, text.Length);
for (var line_index = 0; line_index < lineNum.Length; line_index++)
{
var line_number = lineNum[line_index];
text[line_number] = text[line_number].Replace(previousFiles[line_index], filenameset[line_index / 2]);
}
buildNewFile(text_copy, Info.baseFolder + "networks\\" + Info.dsnFilename + iterator + ".dsn");
}
}
此代码只获取枚举器的结果并为您生成文件。基于示例代码的假设是每个文件位置每个文件使用两次(因为lineNum
数组的长度是files
位置数的两倍。
我还没有完全测试所有代码,但算法的关键在那里。关键是将数据转换为更有用的形式,然后进行处理。我在这里提出问题时的另一个建议是将问题更多地描述为“问题”而不是当前解决方案。如果您详细说明了您尝试实现的目标而不是显示代码,则可以更深入地了解问题。