Создать текстовые файлы каждой комбинации определенных строк в базовом текстовом файле - PullRequest
0 голосов
/ 19 июня 2010

Хорошо, надеюсь, я смогу объяснить это достаточно подробно, чтобы кто-нибудь смог мне помочь ... Я пишу программу на C #, которая должна принимать текстовый файл и заменять определенный текст, который, как оказалось, является именем файлы, и распечатать новый текстовый файл для каждой комбинации заданных имен файлов. Определенные места для изменения текста имен файлов имеют свой собственный набор возможных имен файлов, перечисленных в виде массива, описанного ниже. Программа должна работать независимо от того, сколько имен файлов доступно для каждого местоположения, а также сколько общих мест для имен файлов. Если вы действительно хотите сделать его потрясающим, его можно немного оптимизировать, зная, что никакие имена файлов не должны дублироваться в любом текстовом файле.

text - это массив строк, составляющих основу всего файла.

lineNum содержит массив местоположений строк в именах файлов.

previousFiles - это массив ранее использованных имен файлов, начиная с того, что уже есть в файле.

files - это зубчатый 2-мерный массив возможных имен файлов, где files[1] будет массивом всех возможных имен файлов для 2-го местоположения

Вот пример того, как он будет работать с 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");
                }
            }
        }

Если вы, ребята, можете мне помочь, большое спасибо, я просто не могу понять, как сделать это рекурсивно или что-то в этом роде. Если у вас есть какие-либо вопросы, я отвечу на них и отредактирую здесь, чтобы отразить это.

1 Ответ

1 голос
/ 19 июня 2010

Мне понадобилось немного времени, чтобы понять, что ты действительно хотел сделать.Эта проблема может быть решена без рекурсии, хитрость заключается в том, чтобы просмотреть имеющиеся у вас данные и перевести их в более удобный для использования формат.

Ваш массив "files" является наиболее неудобным.Хитрость заключается в том, чтобы преобразовать данные в пригодные для использования перестановки.Для этого я предлагаю воспользоваться 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.

Я не полностью протестировал всекод, но суть алгоритма в этом. Ключ заключается в том, чтобы преобразовать ваши данные в более удобную форму, а затем обработать ее. Другое предложение, которое я имею, когда задаю вопрос здесь, это описать проблему больше как «проблему» ине в терминах вашего текущего решения. Если вы не указали код, а подробно описали цель, которую пытаетесь достичь, вы можете получить более полное представление о проблеме.

...