joachim
joachim

Reputation: 30811

A list of Dart StringBuffers seem to interfere with each other

I'm doing a nested iteration over two lists, in which I am populating some StringBuffers, like this:

  var int_list = [1, 2, 3];
  var letters_list = ['a', 'b', 'c'];

  var row_strings = List.filled(3, StringBuffer());
  var single_buffer = StringBuffer();

  int_list.asMap().forEach((int_index, column) {
    letters_list.asMap().forEach((letter_index, letter) {
      // debug the writing operation
      print('writing $letter_index - $letter');

      row_strings[letter_index].write(letter);

      // try a buffer not in a list as a test
      if (letter_index == 0) {
        single_buffer.write(letter);
      }
    });
  });
  print(single_buffer);
  print(row_strings);

What I expect to happen is that in the list of StringBuffers, buffer 0 gets all the 'a's, buffer 1 gets all the 'b's, and buffer 3 the 'c'.

The debug output confirms that the writing operation is doing the right thing:

writing 0 - a
writing 1 - b
writing 2 - c
writing 0 - a
writing 1 - b
writing 2 - c
writing 0 - a
writing 1 - b
writing 2 - c

and the single string buffer gets the right output:

aaa

But the output of the list is this:

[abcabcabc, abcabcabc, abcabcabc]

What is going on here? There seems to be some strange behaviour when the StringBuffers are in a list.

Upvotes: 0

Views: 96

Answers (1)

julemand101
julemand101

Reputation: 31259

Your problem is this line:

  var row_strings = List.filled(3, StringBuffer());

This constructor is documented as:

List.filled(int length, E fill, {bool growable: false})

Creates a list of the given length with fill at each position.

https://api.dart.dev/stable/2.10.5/dart-core/List/List.filled.html

So what you are doing is creating a single StringBuffer instance and uses that on every position in your row_strings list.

What you properly want, is to create a new StringBuffer for each position in the list. You need to use List.generate for that:

List.generate(int length,E generator(int index), {bool growable: true})

Generates a list of values.

Creates a list with length positions and fills it with values created by calling generator for each index in the range 0 .. length - 1 in increasing order.

https://api.dart.dev/stable/2.10.5/dart-core/List/List.generate.html

Using that, we end up with:

  final row_strings = List.generate(3, (_) => StringBuffer());

We don't need the index argument in our generator so I have just called it _. The function (_) => StringBuffer() will be executed for each position in the list and saved. Since out function returns a new instance of StringBuffer each time it is executed, we will end up with a list of 3 separate StringBuffer instances.

Upvotes: 2

Related Questions