By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,201 Members | 920 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,201 IT Pros & Developers. It's quick & easy.

How do you modify an array while iterating through it?

P: n/a
I ran into this problem today: I got an array with Account objects. I need
to iterate through this array to supplement the accounts in the array with
more data. But the compiler complains when I try to modify the objects in
the array while iterating through it. I marked the bugs in this code:

// Loop through all previously added accounts
foreach(Account a in a1) // a1 is an ArrayList
{
// If name and context is the same
if(a.Name == name && a.Context == context)
{
// Add the amount to the existing account object in the array
a.Amount += amount; // BUG!
break;
}
else
{
// Add a new account object to the array
Account newAccount = new Account(name, ns, context, amount);
a1.Add(newAccount); // BUG!
}
}

There is an outer loop where name, context and amount are found. Hope I
provided enough info. What is the right way of doing this?

Gustaf

Nov 15 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Gustaf Liljegren <gu**************@bredband.net> wrote:
I ran into this problem today: I got an array with Account objects. I need
to iterate through this array to supplement the accounts in the array with
more data. But the compiler complains when I try to modify the objects in
the array while iterating through it. I marked the bugs in this code:

// Loop through all previously added accounts
foreach(Account a in a1) // a1 is an ArrayList
{
// If name and context is the same
if(a.Name == name && a.Context == context)
{
// Add the amount to the existing account object in the array
a.Amount += amount; // BUG!
break;
}
else
{
// Add a new account object to the array
Account newAccount = new Account(name, ns, context, amount);
a1.Add(newAccount); // BUG!
}
}

There is an outer loop where name, context and amount are found. Hope I
provided enough info. What is the right way of doing this?


You should be able to change the account itself - the first one
shouldn't be a problem, in other words (unless it's a value type?) -
but the second one is changing the list itself, which you can't do
without it throwing an exception. However, I'm surprised if you get a
*compiler* exception rather than a runtime exception.

Could you produce a short but complete example program which
demonstrates the problem?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #2

P: n/a
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote:
You should be able to change the account itself - the first one
shouldn't be a problem, in other words (unless it's a value type?) -
You're right. This is in fact no problem.
but the second one is changing the list itself, which you can't do
without it throwing an exception. However, I'm surprised if you get a
*compiler* exception rather than a runtime exception.


Rigth again. I learned to separate them now.

So, the problem remaining is how to add another Account within that loop.
The logic is:

1. See if the account already exists in the array.
2. If it does, add a new amount to the old one. If not, create a new account
in the array.

I'll see if I can come up with a simple example to work on.

Gustaf

Nov 15 '05 #3

P: n/a
Gustaf Liljegren <gu**************@bredband.net> wrote:

<snip>
So, the problem remaining is how to add another Account within that loop.
The logic is:

1. See if the account already exists in the array.
2. If it does, add a new amount to the old one. If not, create a new account
in the array.

I'll see if I can come up with a simple example to work on.


You can't change a list while you're iterating through it. One common
solution is to build up another list containing the items you *want* to
add to the list, and then add all of them after you've finished
iterating. (You could use ArrayList.AddRange for that.)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #4

P: n/a

"Gustaf Liljegren" <gu**************@bredband.net> wrote in message
news:et**************@TK2MSFTNGP10.phx.gbl...
So, the problem remaining is how to add another Account within that loop.
The logic is:

1. See if the account already exists in the array.
2. If it does, add a new amount to the old one. If not, create a new account in the array.


You could change the foreach-statement into a for-loop (going backwards).

Or even better. Not use an ArrayList, but a HashTable for the lookup.

Best Regards

- Michael S
Nov 15 '05 #5

P: n/a
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote:
You can't change a list while you're iterating through it. One common
solution is to build up another list containing the items you *want* to
add to the list, and then add all of them after you've finished
iterating. (You could use ArrayList.AddRange for that.)


Thanks for all your help. I see that I have not given a good enough
description. It's a grouping problem. The input data is a list of accounts
(identified by name) where some accounts occurs more than once. I want the
accounts grouped so that the amounts are summed up. For example, this input
data

Account 1: 2.50
Account 2: 7.00
Account 1: 1.50
Account 3: 9.00
Account 2: 3.50
Account 2: 6.00
Account 3: 3.50
Account 1: 6.50

shall result in these groups (each in an Account object):

Account 1: 10.5
Account 2: 16.5
Account 3: 12.5

My way of doing this is looping through the input data, account by account.
If the account has already been found, I just add the amount from the
current account object. If not, I add the whole object to the array. But it
won't work, since I can't add items to the array while iterating through it.

Maybe I need an Accounts collection class with methods like AccountExists(),
AddAccount() and UpdateAmount().

Gustaf

Nov 15 '05 #6

P: n/a
Gustaf Liljegren <gu**************@bredband.net> wrote:
You can't change a list while you're iterating through it. One common
solution is to build up another list containing the items you *want* to
add to the list, and then add all of them after you've finished
iterating. (You could use ArrayList.AddRange for that.)


Thanks for all your help. I see that I have not given a good enough
description. It's a grouping problem. The input data is a list of accounts
(identified by name) where some accounts occurs more than once. I want the
accounts grouped so that the amounts are summed up. For example, this input
data

Account 1: 2.50
Account 2: 7.00
Account 1: 1.50
Account 3: 9.00
Account 2: 3.50
Account 2: 6.00
Account 3: 3.50
Account 1: 6.50

shall result in these groups (each in an Account object):

Account 1: 10.5
Account 2: 16.5
Account 3: 12.5

My way of doing this is looping through the input data, account by account.
If the account has already been found, I just add the amount from the
current account object. If not, I add the whole object to the array. But it
won't work, since I can't add items to the array while iterating through it.


It sounds like you should actually have two different lists (or rather,
a list and a map) - one for the input, and one for the output.
Something like (untested code)

foreach (Account account in inputList)
{
if (outputMap.ContainsKey(account.Name))
{
((Account)outputMap[account.Name]).Amount += account.Amount;
}
else
{
Account copy = new Account (account.Name, account.Amount);
outputMap[copy.Name]=copy;
}
}

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.