Как написать список в текстовый файл.Напишите 50 позиций в строке - PullRequest
0 голосов
/ 03 октября 2018

Я работаю над программой, в которой я читаю данные из файла, сохраняю эти данные в списке и записываю эти данные в новый файл в специальном формате.Я создал метод, чтобы прочитать оригинальный файл и сохранить его в списке.

Файл, из которого я читаю, представляет собой список чисел.Одно число в строке.

У меня проблема с моим методом записи в новый файл.У меня проблема с тем, чтобы взять 50 предметов и записать их в строку, а затем взять следующие 50 предметов и написать на следующей строке.Метод состоит в том, чтобы взять первые 50 элементов и написать их и повторить эти 50 элементов в каждой строке.Я знаю, что это из-за моего второго цикла for.Просто не уверен, как это исправить.любая помощь будет оценена.Ниже мой код:

public static void WriteFormattedTextToNewFile(List<string> groupedStrings)
{
    string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
    StreamWriter sw = new StreamWriter(file, true);

    for (int i = 0; i < ReadFile.GroupedStrings.Count; i++)
    {
        sw.Write($"{DateTime.Now:yyyy MM dd  hh:mm:ss}\t\t");

        for (int j = 0; j < 50; j++)
        {
            sw.Write($"{ReadFile.GroupedStrings[j]}\t");
        }
        sw.WriteLine();
    }
    sw.Close();
}

1 Ответ

0 голосов
/ 04 октября 2018

Я дам вам три варианта (и бонус).

Первый вариант.Используйте пользовательский оператор Chunk(int) linq, используя блоки итераторов.Хитрость в том, что внутренний метод использует тот же перечислитель, что и внешний.Похоже, много кода, но как только у вас есть метод Chunk(), вы можете использовать его где угодно.Также обратите внимание, что эта опция даже не требует List<string>.Он будет работать с any IEnumerable<string>, поскольку мы никогда не ссылаемся ни на какие элементы по индексу.

public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> values, int chunkSize)
{
    var e = values.GetEnumerator();
    while (e.MoveNext())
    {
        yield return innerChunk(e, chunkSize);
    }
}

private static IEnumerable<T> innerChunk<T>(IEnumerator<T> e, int chunkSize)
{
    //If we're here, MoveNext() was already called once to advance between batches
    // Need to yield the value from that call.
    yield return e.Current;

    //start at 1, not 0, for the first yield above  
    int i = 1; 
    while(i++ < chunkSize && e.MoveNext()) //order of these conditions matters
    {
        yield return e.Current;
    }
}

public static void WriteFormattedTextToNewFile(IEnumerable<string> groupedStrings)
{
    string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
    using (var sw = new StreamWriter(file, true))
    {   
        foreach(var strings in groupedStrings.Chunk(50))
        {
            sw.Write($"{DateTime.Now:yyyy MM dd  hh:mm:ss}\t\t");
            foreach(var item in strings)
            {
               sw.Write($"{item}\t");
            }
            sw.WriteLine();
        } 
    }
}

Вот базовое доказательство концепции, что Chunk () на самом деле работает .

В качестве бонуса, здесь есть еще один способ использовать метод Chunk() из первого варианта.Обратите внимание, насколько маленьким и понятным становится фактический метод, но построение длинных строк полной строки, вероятно, делает это менее эффективным.

public static void WriteFormattedTextToNewFile(IEnumerable<string> groupedStrings)
{
    string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
    using (var sw = new StreamWriter(file, true))
    {   
        foreach(var strings in groupedStrings.Chunk(50))
        {
            sw.Write($"{DateTime.Now:yyyy MM dd  hh:mm:ss}\t\t");
            sw.WriteLine(string.Join("\t", strings));
        } 
    }
}

Второй вариант.Следите, используя отдельное целое число / цикл.Обратите внимание на дополнительное условие во внутреннем цикле, все еще используя значение i вместо j для ссылки на текущую позицию и увеличивая i во внутреннем цикле.Это называется цикл управления / прерывания.Обратите внимание, как мы можем записать конечную строку и начальное значение даты в каждой строке, чтобы они также отображались в правильном порядке в коде: сначала заголовок, затем элементы, затем нижний колонтитул, и мы делаем это без сложных условных проверок.

public static void WriteFormattedTextToNewFile(List<string> groupedStrings)
{
    string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
    using (var sw = new StreamWriter(file, true))
    {   
        int i = 0;
        while(i < groupedStrings.Count)
        {
           sw.Write($"{DateTime.Now:yyyy MM dd  hh:mm:ss}\t\t");
           for(int j = 0; j < 50 && i < groupedStrings.Count; j++)
           {
              sw.Write($"{groupedStrings[i]}\t");
              i++;
           }
           sw.WriteLine();
        }
    }
}

Третий вариант.Следите, используя оператор модуля (%).Эта опция (или аналогичная опция, использующая второе значение j в том же цикле) - это то место, где многие обращаются первыми, но будьте осторожны;этот вариант обманчиво трудно понять правильно, тем более что проблема усложняется.

public static void WriteFormattedTextToNewFile(List<string> groupedStrings)
{
    string file = @"C:\Users\e011691\Desktop\New folder\formatted.txt";
    using (var sw = new StreamWriter(file, true))
    {
        for(int i = 0; i < groupedStrings.Count;i++)
        {
            if (i % 50 == 0)
            {
                if (i > 0) sw.WriteLine();
                sw.Write($"{DateTime.Now:yyyy MM dd  hh:mm:ss}\t\t");
            }

            sw.Write($"{groupedStrings[i]}\t");
        }
        sw.WriteLine();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...