创建基本文本文件中特定行的每种组合的文本文件

发布于 2024-09-06 01:55:53 字数 1727 浏览 2 评论 0原文

好的,希望我能足够详细地解释这一点,以便有人能够帮助我。我正在用 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");
                }
            }
        }

如果你们能帮助我,非常感谢,我只是不知道如何递归或其他什么。如果您有任何问题,我会回答并在此处进行编辑以反映这一点。

Ok, so hopefully I can explain this in enough detail for somebody to be able to help me.. I am writing a program in C# that is supposed to take a text file and replace specific text, which happen to be names of files, and print a new text file for every single combination of the given filenames. The specific places to change the text of filenames have their own set of possible filenames, listed as an array described below. The program should run regardless of how many filenames are available for each location as well as how many total locations for the filenames. If you really wanted to make it awesome, it can be slightly optimized knowing that no filenames should be duplicated throughout any single text file.

text is an array of lines that make up the base of the total file.

lineNum holds an array of the line locations of the filename entries.

previousFiles is an array of previously used filenames, starting with what is already in the file.

files is a jagged 2-dimensional array of possible filenames where files[1] would be an array of all the possible filenames for the 2nd location

Here is an example of how it would work with 3 separate filename locations, the first one given 3 possible filenames, the second given 8 possible filenames, and the third given 3 possible filenames.

Oh and assume buildNewFile works.

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

If you guys can help me, thank you so much, I just can't figure out how to do it recursively or anything. If you have any questions I'll answer them and edit up here to reflect that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

顾忌 2024-09-13 01:55:53

我花了一段时间才弄清楚你真正想做什么。这个问题可以不用递归来解决,诀窍是查看您拥有的数据并将其转换为更可用的格式。

您的“文件”数组是最不方便的数组。诀窍是将数据转换为可用的排列。为此,我建议利用 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 二维数组的每一行的当前索引,并返回每个当前索引处的文件名。然后它增加第一个索引。如果第一个索引翻转,则它会重置为 0 并递增下一个索引。这样我们就可以迭代文件名的每个排列。

现在,查看 lineNumfiles 之间的关系,我假设文件中的每个位置都被复制到两行。其余的代码在这里:

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 位置计数的两倍。

我没有全面测试了所有代码,但算法的关键在于将数据转换为更可用的形式,然后对其进行处理。在此处提出问题时,我的另一个建议是将问题描述为一个问题。 “问题”而不是当前解决方案的术语。如果您详细说明了要实现的目标而不是显示代码,则可以更深入地了解问题。

It took me a little while to figure out what you really wanted to do. This problem can be solved without recursion, the trick is to look at the data you have and get it into a more usable format.

Your "files" array is the one that is the most inconvenient. The trick is to transform the data into usable permutations. To do that, I suggest taking advantage of yield and using a method that returns IEnumerable. The code for it is here:

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

Basically, it keeps track of the current index for each row of the files 2D array and returns the file name at each current index. Then it increments the first index. If the first index rolls over, then it resets to 0 and increments the next index instead. This way we can iterate through every permutation of the file names.

Now, looking at the relationship between lineNum and files, I assume that each location in the file is copied to two lines. The rest of the code is here:

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

This code just takes the results from the enumerator and generates the files for you. The assumption based on your sample code is that each filename location is used twice per file (since the lineNum array was twice as long as the files location count.

I haven't fully tested all the code, but the crux of the algorithm is there. The key is to transform your data into a more usable form, then process it. The other suggestion I have when asking a question here is to describe the problem more as a "problem" and not in the terms of your current solution. If you detailed the goal you are trying to achieve instead of showing code, you can get more insights into the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文