1

I have a list which contains 91 items in it. I currently loop over and write each line to a text file using StreamWriter. I want to divide the list by 3 so after 30 items I want to insert a blank line. So far I have

foreach (var item in textList)
{
   //write to file
   counter++;
   if (counter == totalItems / 3)
   {
      await sw.WriteLineAsync(Environment.NewLine);
   }
}

but it only works for the first 30 items. Please note the list can contain any number of items but this particular one contains 91. However I will always have to divide into 3.

Izzy
  • 6,740
  • 7
  • 40
  • 84
  • 3
    You have to reset your `counter` to `0` after writing the blank line. – pappbence96 Oct 08 '19 at 14:51
  • 1
    You're telling it to call WriteLineAsync() *once*: When counter is equal to 30. You want the [modulus operator](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/arithmetic-operators#remainder-operator-) if you're going to care about the final count, or reset as pappenbence suggests. – 15ee8f99-57ff-4f92-890c-b56153 Oct 08 '19 at 14:51
  • 2
    `if (counter % 30 == 0) {...}` after each `30` items do something – Dmitry Bychenko Oct 08 '19 at 14:52
  • Possible duplicate of [On every third iteration C#](https://stackoverflow.com/questions/43280680/on-every-third-iteration-c-sharp) – Sinatr Oct 08 '19 at 14:52

2 Answers2

3

You either want to divide a list of 91 items by 3 or after 30 items. You can't have both. If you do it after every 30 items, you would have the 91st item separated from the rest, on its own 'chunk', i,e. 1-30, 31-60, 61-90, 91. If you have 91 items, and want to split by 3, you should do it every 31 items (hence why I am using Math.Ceiling). That way you'd have 1-31, 32-62 and 63-91.

Also, don't use foreach AND a counter; use the for loop instead. And you can use the modulus operator. As so:

int third = Convert.ToInt32(Math.Ceiling(textList.Count / 3.0));
int divider = third - 1;

for (int i = 0; i < textList.Count; i++)
{
    var itemToWrite = textList[i];
    //write to file

    if (i % third == divider) await sw.WriteLineAsync(Environment.NewLine);
}
Mark Cilia Vincenti
  • 1,410
  • 8
  • 25
0

Use modulo. Try like:

 if (counter % (totalItems / 3) == 0)
 {
   ...
apomene
  • 14,282
  • 9
  • 46
  • 72
  • How will this work if I had a list containing say only 20 items? I'd still want it to split in 3 – Izzy Oct 08 '19 at 14:54
  • 1
    If totalItems is 20, there will be 3 dividers; between 6 and 7, between 12 and 13 and between 18 and 19. I don't think this is what @Code wants because that splits it in 4 not 3. https://stackoverflow.com/a/58288918/9945524 – Mark Cilia Vincenti Oct 08 '19 at 15:08