If you need to mutate the array, there's #reject! On Oct 15, 2009, at 0:23, Rob Kaufman <[email protected]> wrote:
> > Martin mentions the reject method, which creates returns a new array, > it doesn't function on the existing array: > > a = [1,2,3,4,5] > => [1, 2, 3, 4, 5] > a.reject do |i| i == 5 end > => [1, 2, 3, 4] > a > => [1, 2, 3, 4, 5] > > However manipulating the value i during the iteration does not get > returned but it is what gets compared with. For example > > a.reject do |i| > i += 5 > puts i > i == 6 > end >> 6 >> 7 >> 8 >> 9 >> 10 > => [2, 3, 4, 5] > > I have to agree with Pat that you usually don't want to modify the > array, but instead make a new one with the subset you care about. > reject or select are much better for that than each and delete or even > reverse_each and delete. The cost of making the new Array is trivial > and actually much smaller than modifying the memory position of each > element several times as it collapses toward the front. Having said > that if your manipulating the values AND trying to remove some on the > same pass your options are pretty limited. At that point you can do > reverse_each or you can do inject. Inject is the best in that > scenario: > > result = a.inject([]) do |new_array, i| > i += 5 > if i == 6 > new_array # This is the value that becomes new_array on the next > pass > else > new_array << i > end > end > => [7, 8, 9, 10] > > Best, > Rob > > On Wed, Oct 14, 2009 at 10:22, Pat Allan <[email protected]> > wrote: >> >> Modifying an array while enumerating over it - no matter what method >> you're using - is not a good idea. >> >> Also, if you just want to remove everything in an array: >> array = ['a', 'b', 'c'] >> array.clear >> array #=> [] >> >> Cheers >> >> -- >> Pat >> >> On 14/10/2009, at 6:48 PM, James Miller wrote: >> >>> Your explanation got me thinking that iterating in reverse might >>> work...it does! >>> >>> array = [ "a", "b", "c" ] >>> array.reverse_each do |item| >>> array.delete(item) >>> end >>> >>> array => [] >>> >>> Sweeeet.... >>> >>> On Wed, Oct 14, 2009 at 9:40 AM, James Miller >>> <[email protected]> wrote: >>> Kerry - I ended up just creating a new array and adding elements to >>> it that I do want, which works fine. Thanks for the explanation, >>> makes sense. >>> >>> David - Thanks for the explanation as well. There's more code >>> involved in the actual implementation, where the array will >>> sometimes still contain items and sometimes be emptied in the >>> iteration. My example was just to simplify and show the weirdness >>> when trying to empty the array via iteration rather than just >>> setting to []. >>> >>> Thanks, >>> James >>> >>> >>> On Wed, Oct 14, 2009 at 9:31 AM, Kerry Foley >>> <[email protected]> wrote: >>> >>> Hi James, >>> Strange right? Well, when you call delete within the loop it >>> confuses >>> each. The first time in you delete "a". The second time in you go to >>> the >>> 2nd element of the array, which is now "c" (not "b"). So you delete >>> "c" >>> and are left with array => ["b"]. >>> >>> I assume you are are doing other things within the loop so one way >>> is to >>> save the items you want to delete into another array i.e. >>> to_be_deleted >>> and then do the deleting once you have exited the loop. >>> >>> Regards, >>> Kerry >>> >>> James Miller wrote: >>>> Hi Everyone, >>>> >>>> Wondering if someone could explain why this doesn't work as (I) >>>> expected... >>>> >>>> array = [ "a", "b", "c" ] >>>> >>>> array.each do |item| >>>> array.delete(item) >>>> end >>>> >>>> array => [ "b" ] >>>> >>>> Why isn't the array empty ( array => [] )? Is there a better >>> approach? >>>> >>>> Thanks, >>>> James >>>> >>>> >>>>> >>> >>> >>> >>> >>> >>> >>>> >> >> >>> >> > > > > -- > Rob Kaufman > http://notch8.com > gtalk/jabber/email: [email protected] > p: 858-412-7749 > f: 866-477-1620 > > > --~--~---------~--~----~------------~-------~--~----~ SD Ruby mailing list [email protected] http://groups.google.com/group/sdruby -~----------~----~----~----~------~----~------~--~---
