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
-~----------~----~----~----~------~----~------~--~---