OrderedCollection remove:

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

OrderedCollection remove:

Peter Uhnak
Hi,

I've just run into quite a nasty surprise
~~~~~~~~~~~~~~~~
col := #(1 2 3 4 5) asOrderedCollection.
col do: [ :each | col remove: each. ].
col
~~~~~~~~~~~~~~~~
it throws "NotFound: nil not found in OrderedCollection"
I tested it also in Pharo3 and there it just silently removed first, third and fifth element.

Looking at the implementation of OrderedCollection>>do:  it seems that doing what I'm doing is a bad idea.

So what shall one do:? col copy do: [...] ?

Why can't do: be a bit smarter? Optimization?

Thanks,
Peter
Reply | Threaded
Open this post in threaded view
|

Re: OrderedCollection remove:

jtuchel
Peter,

In general, removing from a Collection while iterating through it leads to undefined results. The same is true for adding.

Just never do it

Joachim



> Am 02.04.2015 um 08:22 schrieb Peter Uhnák <[hidden email]>:
>
> Hi,
>
> I've just run into quite a nasty surprise
> ~~~~~~~~~~~~~~~~
> col := #(1 2 3 4 5) asOrderedCollection.
> col do: [ :each | col remove: each. ].
> col
> ~~~~~~~~~~~~~~~~
> it throws "NotFound: nil not found in OrderedCollection"
> I tested it also in Pharo3 and there it just silently removed first, third and fifth element.
>
> Looking at the implementation of OrderedCollection>>do:  it seems that doing what I'm doing is a bad idea.
>
> So what shall one do:? col copy do: [...] ?
>
> Why can't do: be a bit smarter? Optimization?
>
> Thanks,
> Peter

Reply | Threaded
Open this post in threaded view
|

RE: OrderedCollection remove:

BriceG
In reply to this post by Peter Uhnak
Hi,
it depends on what is your goal but if you want to clean an OrderedCollection there's removeAll of if you want to remove specific item there's removeAllSuchThat:aBlock

I had the following code working for your example:

col := #(1 2 3 4 5) asOrderedCollection.
a := col select:[:each| col includes:each].
col removeAllSuchThat: [ :each| a includes:each ].
col

as you suggested, I'm creating a new collection with all the element I want to remove and then I remove each of its item from the first collection.

Regards,



--------------
Brice Govin
PhD student in RMoD research team at INRIA Lille
Software Engineer at THALES AIR SYSTEMS Rungis
ENSTA-Bretagne ENSI2014
64 chemin des boeufs 91220 PALAISEAU


De : Peter Uhnák [via Smalltalk] <ml-node+[hidden email]>
Envoyé : jeudi 2 avril 2015 08:11
À : Brice GOVIN
Objet : OrderedCollection remove:
 
Hi,

I've just run into quite a nasty surprise
~~~~~~~~~~~~~~~~
col := #(1 2 3 4 5) asOrderedCollection.
col do: [ :each | col remove: each. ].
col
~~~~~~~~~~~~~~~~
it throws "NotFound: nil not found in OrderedCollection"
I tested it also in Pharo3 and there it just silently removed first, third and fifth element.

Looking at the implementation of OrderedCollection>>do:  it seems that doing what I'm doing is a bad idea.

So what shall one do:? col copy do: [...] ?

Why can't do: be a bit smarter? Optimization?

Thanks,
Peter



If you reply to this email, your message will be added to the discussion below:
http://forum.world.st/OrderedCollection-remove-tp4816822.html
To unsubscribe from Pharo Smalltalk Users, click here.
NAML
Reply | Threaded
Open this post in threaded view
|

Re: OrderedCollection remove:

Peter Uhnak
In reply to this post by jtuchel
On Thu, Apr 2, 2015 at 8:30 AM, Joachim Tuchel <[hidden email]> wrote:
In general, removing from a Collection while iterating through it leads to undefined results. The same is true for adding.
That is a question of approach; apart from mentioned #copy I could also do something like
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
col := #(1 2 3 4 5) asOrderedCollection.
[col isNotEmpty] whileTrue: [ col remove: col first ].
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if I had an Iterator I could also reset it after each change.

What I am asking is what the best approach would be - I want do some processing for each item and remove it from the collection after it is done.

Peter
Reply | Threaded
Open this post in threaded view
|

Re: OrderedCollection remove:

philippeback
In reply to this post by Peter Uhnak
On Thu, Apr 2, 2015 at 8:22 AM, Peter Uhnák <[hidden email]> wrote:
Hi,

I've just run into quite a nasty surprise
~~~~~~~~~~~~~~~~
col := #(1 2 3 4 5) asOrderedCollection.
col do: [ :each | col remove: each. ].
col
~~~~~~~~~~~~~~~~
it throws "NotFound: nil not found in OrderedCollection"
I tested it also in Pharo3 and there it just silently removed first, third and fifth element.

Looking at the implementation of OrderedCollection>>do:  it seems that doing what I'm doing is a bad idea.

So what shall one do:? col copy do: [...] ?

Yes, as a general rule, do not modify a collection you are iterating on, so, doing col copy do: looks right. 

removeAllSuchThat: aBlock 
"Evaluate aBlock for each element and remove all that elements from
the receiver for that aBlock evaluates to true.  Use a copy to enumerate 
collections whose order changes when an element is removed (i.e. Sets)."

self copy do: [:each | (aBlock value: each) ifTrue: [self remove: each]]

If the collection is huge, that can be an issue.


Why can't do: be a bit smarter? Optimization?

If you have the group of things to remove you can do 

aCollection removeAll: anotherCollection

Phil
 

Thanks,
Peter



 

Reply | Threaded
Open this post in threaded view
|

Re: OrderedCollection remove:

philippeback
In reply to this post by Peter Uhnak


On Thu, Apr 2, 2015 at 9:33 AM, Peter Uhnák <[hidden email]> wrote:
On Thu, Apr 2, 2015 at 8:30 AM, Joachim Tuchel <[hidden email]> wrote:
In general, removing from a Collection while iterating through it leads to undefined results. The same is true for adding.
That is a question of approach; apart from mentioned #copy I could also do something like
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
col := #(1 2 3 4 5) asOrderedCollection.
[col isNotEmpty] whileTrue: [ col remove: col first ].
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if I had an Iterator I could also reset it after each change.

What I am asking is what the best approach would be - I want do some processing for each item and remove it from the collection after it is done.

"If process indicates if it is worth removing the item"
processed:= col select: [ :each |  col process: each ].
col removeAll: processed.

It is an interesting dicussion actually :-)

Phil


 

Peter




Reply | Threaded
Open this post in threaded view
|

RE: OrderedCollection remove:

Sean P. DeNigris
Administrator
In reply to this post by BriceG
BriceG wrote
Hi,
it depends on what is your goal but if you want to clean an OrderedCollection there's removeAll of if you want to remove specific item there's removeAllSuchThat:aBlock

I had the following code working for your example:

col := #(1 2 3 4 5) asOrderedCollection.
a := col select:[:each| col includes:each].
col removeAllSuchThat: [ :each| a includes:each ].
col

as you suggested, I'm creating a new collection with all the element I want to remove and then I remove each of its item from the first collection.

Regards,



--------------
Brice Govin
PhD student in RMoD research team at INRIA Lille
Software Engineer at THALES AIR SYSTEMS Rungis
ENSTA-Bretagne ENSI2014
64 chemin des boeufs 91220 PALAISEAU
________________________________
De : Peter Uhnák [via Smalltalk] <[hidden email]>
Envoyé : jeudi 2 avril 2015 08:11
À : Brice GOVIN
Objet : OrderedCollection remove:

Hi,

I've just run into quite a nasty surprise
~~~~~~~~~~~~~~~~
col := #(1 2 3 4 5) asOrderedCollection.
col do: [ :each | col remove: each. ].
col
~~~~~~~~~~~~~~~~
it throws "NotFound: nil not found in OrderedCollection"
I tested it also in Pharo3 and there it just silently removed first, third and fifth element.

Looking at the implementation of OrderedCollection>>do:  it seems that doing what I'm doing is a bad idea.

So what shall one do:? col copy do: [...] ?

Why can't do: be a bit smarter? Optimization?

Thanks,
Peter


________________________________
If you reply to this email, your message will be added to the discussion below:
http://forum.world.st/OrderedCollection-remove-tp4816822.html
To unsubscribe from Pharo Smalltalk Users, click here<http://forum.world.st/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=1310670&code=YnJpY2UuZ292aW5AZW5zdGEtYnJldGFnbmUub3JnfDEzMTA2NzB8MTQ0Nzk1ODcwOA==>.
NAML<http://forum.world.st/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: OrderedCollection remove:

jtuchel
In reply to this post by Peter Uhnak
Peter,

several approaches have been shown already. I'd like to add:

* Iterate over a copy and remove from the original (slower because of lookup in the original)
* If possible, sort the collection and use something like [col atEnd] whileTrue:/whileFalse: with removeFirst/removeLast
* Select: a collection of items to be removed and then do a removeAll:
* Use #- to remove one collection from the other
* Iterate over the original and add only the wanted objects to a new collection which will then be used in the future - Streams may be helpful here
* I have never used XStreams, but there may even be some nice options to find in it

HTH

Joachim



Am 02.04.15 um 09:33 schrieb Peter Uhnák:
On Thu, Apr 2, 2015 at 8:30 AM, Joachim Tuchel <[hidden email]> wrote:
In general, removing from a Collection while iterating through it leads to undefined results. The same is true for adding.
That is a question of approach; apart from mentioned #copy I could also do something like
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
col := #(1 2 3 4 5) asOrderedCollection.
[col isNotEmpty] whileTrue: [ col remove: col first ].
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if I had an Iterator I could also reset it after each change.

What I am asking is what the best approach would be - I want do some processing for each item and remove it from the collection after it is done.

Peter

Reply | Threaded
Open this post in threaded view
|

Re: OrderedCollection remove:

abergel
In reply to this post by Peter Uhnak
col := #(1 2 3 4 5) asOrderedCollection.
col copy do: [ :each | col remove: each. ].
col

will work instead

Alexandre
--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel  http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.



> On Apr 2, 2015, at 3:22 AM, Peter Uhnák <[hidden email]> wrote:
>
> Hi,
>
> I've just run into quite a nasty surprise
> ~~~~~~~~~~~~~~~~
> col := #(1 2 3 4 5) asOrderedCollection.
> col do: [ :each | col remove: each. ].
> col
> ~~~~~~~~~~~~~~~~
> it throws "NotFound: nil not found in OrderedCollection"
> I tested it also in Pharo3 and there it just silently removed first, third and fifth element.
>
> Looking at the implementation of OrderedCollection>>do:  it seems that doing what I'm doing is a bad idea.
>
> So what shall one do:? col copy do: [...] ?
>
> Why can't do: be a bit smarter? Optimization?
>
> Thanks,
> Peter


Reply | Threaded
Open this post in threaded view
|

Re: OrderedCollection remove:

Ramon Leon-5
In reply to this post by Peter Uhnak
On 04/01/2015 11:22 PM, Peter Uhnák wrote:
> col := #(1 2 3 4 5) asOrderedCollection.
> col do: [ :each | col remove: each. ].
> col

As a general rule in Smalltalk, a lot of hassle can be avoided avoiding
loops.  If you think you need a loop, stop and find a better way, it
likely already exists, in this case as someone else already mentioned
either #removeAll: or #removeSuchThat:.  Smalltalk isn't procedural,
loops aren't your bread and butter.

--
Ramon Leon