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

Reply via email to