remove ArrayList[n] inside foreach() loop?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?Utf-8?B?YmJn?=

    #1

    remove ArrayList[n] inside foreach() loop?

    Hi all,

    I wanted to go through each entry(?) of ArrayList and remove some particular
    entry. So I tried following but it throws exception at runtime:

    foreach (myEntry entry in myArrayList)
    {
    // do something...

    if (entry.fieldA == 0)
    { // remove entry
    myArrayList.Rem ove(entry); // exception below
    } // remove entry
    }

    /* exception:
    System.InvalidO perationExcepti on: Collection was modified; enumeration
    operation may not execute.
    at System.Collecti ons.ArrayList.A rrayListEnumera torSimple.MoveN ext()
    */

    So I had to create an index array to remove and remove indexed entries
    outside of foreach() loop. Is this a natural way to do or is there a better
    way?

    Regards

    Bob
  • Ignacio Machin \( .NET/ C# MVP \)

    #2
    Re: remove ArrayList[n] inside foreach() loop?

    Hi,

    "bbg" <bbg@discussion s.microsoft.com wrote in message
    news:0FEE11EE-1CB1-47AD-A828-1B8511D8E66B@mi crosoft.com...
    Hi all,
    >
    I wanted to go through each entry(?) of ArrayList and remove some
    particular
    entry. So I tried following but it throws exception at runtime:
    >
    foreach (myEntry entry in myArrayList)
    {
    // do something...
    >
    if (entry.fieldA == 0)
    { // remove entry
    myArrayList.Rem ove(entry); // exception below
    } // remove entry
    }
    >
    /* exception:
    System.InvalidO perationExcepti on: Collection was modified; enumeration
    operation may not execute.
    at System.Collecti ons.ArrayList.A rrayListEnumera torSimple.MoveN ext()
    */
    >
    So I had to create an index array to remove and remove indexed entries
    outside of foreach() loop. Is this a natural way to do or is there a
    better
    way?
    You cannot modify the collection you are iterating in. You have to keep
    track of those elements that you want removed and remove them after the
    colection is iterate. A way of doing it is
    ArrayList toremove = new ...
    foreach (myEntry entry in myArrayList)
    {
    // do something...

    if (entry.fieldA == 0)
    toremove.Add( entry)
    }
    foreach(myEntry entry in toremove )
    myArrayList.Rem ove( entry);



    Comment

    • Nicholas Paldino [.NET/C# MVP]

      #3
      Re: remove ArrayList[n] inside foreach() loop?

      Or, if you want to prevent having to make two iterations, you could just
      iterate backwards through the list (so you can consistently traverse the
      items in the list as you remove them) and remove the items as needed:

      for (int index = myArrayList.Cou nt - 1; index >= 0; index--)
      {
      // Get the item.
      myEntry entry = (myEntry) myArrayList[index];

      // Check to remove.
      if (entry.fieldA == 0)
      {
      // Remove.
      myArrayList.Rem oveAt(index);
      }
      }


      --
      - Nicholas Paldino [.NET/C# MVP]
      - mvp@spam.guard. caspershouse.co m

      "Ignacio Machin ( .NET/ C# MVP )" <machin TA laceupsolutions .comwrote in
      message news:%23jHVI1O6 HHA.4476@TK2MSF TNGP06.phx.gbl. ..
      Hi,
      >
      "bbg" <bbg@discussion s.microsoft.com wrote in message
      news:0FEE11EE-1CB1-47AD-A828-1B8511D8E66B@mi crosoft.com...
      >Hi all,
      >>
      >I wanted to go through each entry(?) of ArrayList and remove some
      >particular
      >entry. So I tried following but it throws exception at runtime:
      >>
      > foreach (myEntry entry in myArrayList)
      > {
      > // do something...
      >>
      > if (entry.fieldA == 0)
      > { // remove entry
      > myArrayList.Rem ove(entry); // exception below
      > } // remove entry
      > }
      >>
      >/* exception:
      >System.Invalid OperationExcept ion: Collection was modified; enumeration
      >operation may not execute.
      > at System.Collecti ons.ArrayList.A rrayListEnumera torSimple.MoveN ext()
      >*/
      >>
      >So I had to create an index array to remove and remove indexed entries
      >outside of foreach() loop. Is this a natural way to do or is there a
      >better
      >way?
      >
      You cannot modify the collection you are iterating in. You have to keep
      track of those elements that you want removed and remove them after the
      colection is iterate. A way of doing it is
      ArrayList toremove = new ...
      foreach (myEntry entry in myArrayList)
      {
      // do something...
      >
      if (entry.fieldA == 0)
      toremove.Add( entry)
      }
      foreach(myEntry entry in toremove )
      myArrayList.Rem ove( entry);
      >
      >
      >

      Comment

      • bob

        #4
        Re: remove ArrayList[n] inside foreach() loop?

        On Mon, 27 Aug 2007 13:44:00 -0700, bbg
        <bbg@discussion s.microsoft.com wrote:
        Hi,
        Same theme as Ignacio,
        But I would be tempted to save the wanted members to a new list
        eliminating the remove step.
        Depends I guess on how expensive it is to make a 'myEntry' and the
        ratio of good to bad.
        Bob C.
        >Hi all,
        >
        >I wanted to go through each entry(?) of ArrayList and remove some particular
        >entry. So I tried following but it throws exception at runtime:
        >
        foreach (myEntry entry in myArrayList)
        {
        // do something...
        >
        if (entry.fieldA == 0)
        { // remove entry
        myArrayList.Rem ove(entry); // exception below
        } // remove entry
        }
        >
        >/* exception:
        >System.Invalid OperationExcept ion: Collection was modified; enumeration
        >operation may not execute.
        at System.Collecti ons.ArrayList.A rrayListEnumera torSimple.MoveN ext()
        >*/
        >
        >So I had to create an index array to remove and remove indexed entries
        >outside of foreach() loop. Is this a natural way to do or is there a better
        >way?
        >
        >Regards
        >
        >Bob

        Comment

        • Ben Voigt [C++ MVP]

          #5
          Re: remove ArrayList[n] inside foreach() loop?


          "bob" <startatbob_cle gg@cutthis.adri ley.co.nzwrote in message
          news:hnh6d3tk3k d8djicoe795r0np a45r22r1b@4ax.c om...
          On Mon, 27 Aug 2007 13:44:00 -0700, bbg
          <bbg@discussion s.microsoft.com wrote:
          Hi,
          Same theme as Ignacio,
          But I would be tempted to save the wanted members to a new list
          eliminating the remove step.
          Depends I guess on how expensive it is to make a 'myEntry' and the
          ratio of good to bad.
          Bob C.
          That's what System.Collecti ons.Generic.Lis t<T>.RemoveAll does.

          Most any use of ArrayList can be replaced by List<objectif not something
          more typesafe.


          Comment

          • Alvin Bruney [MVP]

            #6
            Re: remove ArrayList[n] inside foreach() loop?

            Nope, there's an easier way to do this without the hocus pocus. Here is the
            proof of concepts:

            using System;
            using System.Collecti ons.Generic;
            using System.Text;

            namespace ConsoleApplicat ion2
            {
            class Program
            {
            static void Main(string[] args)
            {
            System.Collecti ons.ArrayList arr = new
            System.Collecti ons.ArrayList() ;
            arr.Add("1");
            arr.Add("2");
            arr.Add("3");

            /*This throws an exception
            foreach (string s in arr)
            {
            arr.Remove(s);
            }
            */

            //where as this works like a charm
            Console.WriteLi ne(arr.Count);
            foreach (string s in new System.Collecti ons.ArrayList(a rr))
            {
            arr.Remove(s);
            }
            Console.WriteLi ne(arr.Count);
            Console.ReadKey ();
            }
            }
            }


            --
            Regards,
            Alvin Bruney
            ------------------------------------------------------
            Shameless author plug
            Excel Services for .NET - MS Press
            Professional VSTO 2005 - Wrox/Wiley
            OWC Black Book www.lulu.com/owc

            "bbg" <bbg@discussion s.microsoft.com wrote in message
            news:0FEE11EE-1CB1-47AD-A828-1B8511D8E66B@mi crosoft.com...
            Hi all,
            >
            I wanted to go through each entry(?) of ArrayList and remove some
            particular
            entry. So I tried following but it throws exception at runtime:
            >
            foreach (myEntry entry in myArrayList)
            {
            // do something...
            >
            if (entry.fieldA == 0)
            { // remove entry
            myArrayList.Rem ove(entry); // exception below
            } // remove entry
            }
            >
            /* exception:
            System.InvalidO perationExcepti on: Collection was modified; enumeration
            operation may not execute.
            at System.Collecti ons.ArrayList.A rrayListEnumera torSimple.MoveN ext()
            */
            >
            So I had to create an index array to remove and remove indexed entries
            outside of foreach() loop. Is this a natural way to do or is there a
            better
            way?
            >
            Regards
            >
            Bob

            Comment

            • Ben Voigt [C++ MVP]

              #7
              Re: remove ArrayList[n] inside foreach() loop?


              "Alvin Bruney [MVP]" <some guy without an email addresswrote in message
              news:%23OP9Wad6 HHA.1212@TK2MSF TNGP05.phx.gbl. ..
              Nope, there's an easier way to do this without the hocus pocus. Here is
              the proof of concepts:
              Sure, but it's the most inefficient solution posted yet.
              >
              using System;
              using System.Collecti ons.Generic;
              using System.Text;
              >
              namespace ConsoleApplicat ion2
              {
              class Program
              {
              static void Main(string[] args)
              {
              System.Collecti ons.ArrayList arr = new
              System.Collecti ons.ArrayList() ;
              arr.Add("1");
              arr.Add("2");
              arr.Add("3");
              >
              /*This throws an exception
              foreach (string s in arr)
              {
              arr.Remove(s);
              }
              */
              >
              //where as this works like a charm
              Console.WriteLi ne(arr.Count);
              foreach (string s in new System.Collecti ons.ArrayList(a rr))
              {
              arr.Remove(s);
              }
              Console.WriteLi ne(arr.Count);
              Console.ReadKey ();
              }
              }
              }
              >
              >
              --
              Regards,
              Alvin Bruney
              ------------------------------------------------------
              Shameless author plug
              Excel Services for .NET - MS Press
              Professional VSTO 2005 - Wrox/Wiley
              OWC Black Book www.lulu.com/owc
              >
              "bbg" <bbg@discussion s.microsoft.com wrote in message
              news:0FEE11EE-1CB1-47AD-A828-1B8511D8E66B@mi crosoft.com...
              >Hi all,
              >>
              >I wanted to go through each entry(?) of ArrayList and remove some
              >particular
              >entry. So I tried following but it throws exception at runtime:
              >>
              > foreach (myEntry entry in myArrayList)
              > {
              > // do something...
              >>
              > if (entry.fieldA == 0)
              > { // remove entry
              > myArrayList.Rem ove(entry); // exception below
              > } // remove entry
              > }
              >>
              >/* exception:
              >System.Invalid OperationExcept ion: Collection was modified; enumeration
              >operation may not execute.
              > at System.Collecti ons.ArrayList.A rrayListEnumera torSimple.MoveN ext()
              >*/
              >>
              >So I had to create an index array to remove and remove indexed entries
              >outside of foreach() loop. Is this a natural way to do or is there a
              >better
              >way?
              >>
              >Regards
              >>
              >Bob
              >
              >

              Comment

              • Alvin Bruney [MVP]

                #8
                Re: remove ArrayList[n] inside foreach() loop?

                Sure, but it's the most inefficient solution posted yet.
                Did you care to test the code before making that statement?

                If you did, you'd find that the "inefficien cy" is not noticable for 10,000
                items being removed from the collection - at least on my lap top. And that
                isn't even a real world scenario anyway. You should be far more concerned
                with inefficiencies and performance issues due to network bandwidth; SQL
                queries; start up times; and obscure counters to track and flag items for
                deletion before railing about inefficient code.

                if you care to throw in systems programming as a reason for your efficiency
                comment, then you wouldn't even be using arraylists in the first place as
                OPs code showed.

                --
                Regards,
                Alvin Bruney
                ------------------------------------------------------
                Shameless author plug
                Excel Services for .NET - MS Press
                Professional VSTO 2005 - Wrox/Wiley
                OWC Black Book www.lulu.com/owc

                "Ben Voigt [C++ MVP]" <rbv@nospam.nos pamwrote in message
                news:OBv8P6o6HH A.3400@TK2MSFTN GP03.phx.gbl...
                >
                "Alvin Bruney [MVP]" <some guy without an email addresswrote in message
                news:%23OP9Wad6 HHA.1212@TK2MSF TNGP05.phx.gbl. ..
                >Nope, there's an easier way to do this without the hocus pocus. Here is
                >the proof of concepts:
                >
                Sure, but it's the most inefficient solution posted yet.
                >
                >>
                >using System;
                >using System.Collecti ons.Generic;
                >using System.Text;
                >>
                >namespace ConsoleApplicat ion2
                >{
                > class Program
                > {
                > static void Main(string[] args)
                > {
                > System.Collecti ons.ArrayList arr = new
                >System.Collect ions.ArrayList( );
                > arr.Add("1");
                > arr.Add("2");
                > arr.Add("3");
                >>
                > /*This throws an exception
                > foreach (string s in arr)
                > {
                > arr.Remove(s);
                > }
                > */
                >>
                > //where as this works like a charm
                > Console.WriteLi ne(arr.Count);
                > foreach (string s in new System.Collecti ons.ArrayList(a rr))
                > {
                > arr.Remove(s);
                > }
                > Console.WriteLi ne(arr.Count);
                > Console.ReadKey ();
                > }
                > }
                >}
                >>
                >>
                >--
                >Regards,
                >Alvin Bruney
                >------------------------------------------------------
                >Shameless author plug
                >Excel Services for .NET - MS Press
                >Professional VSTO 2005 - Wrox/Wiley
                >OWC Black Book www.lulu.com/owc
                >>
                >"bbg" <bbg@discussion s.microsoft.com wrote in message
                >news:0FEE11E E-1CB1-47AD-A828-1B8511D8E66B@mi crosoft.com...
                >>Hi all,
                >>>
                >>I wanted to go through each entry(?) of ArrayList and remove some
                >>particular
                >>entry. So I tried following but it throws exception at runtime:
                >>>
                >> foreach (myEntry entry in myArrayList)
                >> {
                >> // do something...
                >>>
                >> if (entry.fieldA == 0)
                >> { // remove entry
                >> myArrayList.Rem ove(entry); // exception below
                >> } // remove entry
                >> }
                >>>
                >>/* exception:
                >>System.Invali dOperationExcep tion: Collection was modified; enumeration
                >>operation may not execute.
                >> at System.Collecti ons.ArrayList.A rrayListEnumera torSimple.MoveN ext()
                >>*/
                >>>
                >>So I had to create an index array to remove and remove indexed entries
                >>outside of foreach() loop. Is this a natural way to do or is there a
                >>better
                >>way?
                >>>
                >>Regards
                >>>
                >>Bob
                >>
                >>
                >
                >

                Comment

                • Ben Voigt [C++ MVP]

                  #9
                  Re: remove ArrayList[n] inside foreach() loop?


                  "Alvin Bruney [MVP]" <some guy without an email addresswrote in message
                  news:eA0jhZq6HH A.2380@TK2MSFTN GP02.phx.gbl...
                  >Sure, but it's the most inefficient solution posted yet.
                  Did you care to test the code before making that statement?
                  I don't need to. It makes one additional memory copy vs the "naive"
                  solution of using indexes instead of an iterator.

                  That single copy of the list plus the need to test every element is already
                  more expensive than the straightforward , highly efficient solution of making
                  a new list with just the items not removed, and then your solution also
                  calls Remove a number of times, which not only does a linear search to find
                  the index of the element being removed, it also then moves the other part of
                  the list to close the gap.
                  >
                  If you did, you'd find that the "inefficien cy" is not noticable for 10,000
                  items being removed from the collection - at least on my lap top. And that
                  isn't even a real world scenario anyway. You should be far more concerned
                  with inefficiencies and performance issues due to network bandwidth; SQL
                  queries; start up times; and obscure counters to track and flag items for
                  deletion before railing about inefficient code.
                  There's no reason to write an inefficient version when the framework already
                  provides List<T>.RemoveA ll(Predicate<T> ). Premature optimization deals with
                  rolling your own instead of using an existing function. What you suggested
                  was premature de-optimization -- rolling your own and ending up with worse
                  performance than the existing one.


                  Comment

                  • Jon Skeet [C# MVP]

                    #10
                    Re: remove ArrayList[n] inside foreach() loop?

                    <"Alvin Bruney [MVP]" <some guy without an email address>wrote:
                    Your code does one O(n) pass for each element which needs to be
                    removed. Big difference.
                    Yup, big difference - they both remove 10,000 items in the collection in
                    well under a second. Pretty big difference eh? I'll venture a guess that OPs
                    container holds less than 100 items. What are we saving here? Is this
                    noticeable in production code? Let's not throw around terms like
                    'inefficient' when the context is unclear. These terms only serve to scare
                    developers. If I were reviewing that application for performance, I wouldn't
                    even focus on that piece of code, there's no bang for developer bucks
                    optimizing away milliseconds.
                    You seemed to be considering your code to be linear, that's all. One
                    part is linear, but that's repeated a number of times.

                    Is it a significant inefficiency? That depends on the size of list, and
                    wasn't what I was addressing.

                    --
                    Jon Skeet - <skeet@pobox.co m>
                    http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
                    If replying to the group, please do not mail me too

                    Comment

                    • =?Utf-8?B?YmJn?=

                      #11
                      Re: remove ArrayList[n] inside foreach() loop?

                      I found this way(iterate backwards) was best for me and it worked well.
                      Thanks Nicholas.
                      Bob


                      "Nicholas Paldino [.NET/C# MVP]" wrote:
                      Or, if you want to prevent having to make two iterations, you could just
                      iterate backwards through the list (so you can consistently traverse the
                      items in the list as you remove them) and remove the items as needed:
                      >
                      for (int index = myArrayList.Cou nt - 1; index >= 0; index--)
                      {
                      // Get the item.
                      myEntry entry = (myEntry) myArrayList[index];
                      >
                      // Check to remove.
                      if (entry.fieldA == 0)
                      {
                      // Remove.
                      myArrayList.Rem oveAt(index);
                      }
                      }
                      >
                      >
                      --
                      - Nicholas Paldino [.NET/C# MVP]
                      - mvp@spam.guard. caspershouse.co m
                      >
                      "Ignacio Machin ( .NET/ C# MVP )" <machin TA laceupsolutions .comwrote in
                      message news:%23jHVI1O6 HHA.4476@TK2MSF TNGP06.phx.gbl. ..
                      Hi,

                      "bbg" <bbg@discussion s.microsoft.com wrote in message
                      news:0FEE11EE-1CB1-47AD-A828-1B8511D8E66B@mi crosoft.com...
                      Hi all,
                      >
                      I wanted to go through each entry(?) of ArrayList and remove some
                      particular
                      entry. So I tried following but it throws exception at runtime:
                      >
                      foreach (myEntry entry in myArrayList)
                      {
                      // do something...
                      >
                      if (entry.fieldA == 0)
                      { // remove entry
                      myArrayList.Rem ove(entry); // exception below
                      } // remove entry
                      }
                      >
                      /* exception:
                      System.InvalidO perationExcepti on: Collection was modified; enumeration
                      operation may not execute.
                      at System.Collecti ons.ArrayList.A rrayListEnumera torSimple.MoveN ext()
                      */
                      >
                      So I had to create an index array to remove and remove indexed entries
                      outside of foreach() loop. Is this a natural way to do or is there a
                      better
                      way?
                      You cannot modify the collection you are iterating in. You have to keep
                      track of those elements that you want removed and remove them after the
                      colection is iterate. A way of doing it is
                      ArrayList toremove = new ...
                      foreach (myEntry entry in myArrayList)
                      {
                      // do something...

                      if (entry.fieldA == 0)
                      toremove.Add( entry)
                      }
                      foreach(myEntry entry in toremove )
                      myArrayList.Rem ove( entry);

                      >
                      >
                      >

                      Comment

                      Working...