groovy / grails, no puedo eliminar del mapa

Can you help me identify what is wrong in the simple remove from the map below (notice output right below it)?

  public class Issue {
  ...

  def allButThis() {
    println "allButThis ..."
    def all = Issue.list()
    println "all is ${all}"
    all.remove(this.id)
    println "all with ${this.id} removed: ${all}"
    return all
  }

   String toString() {return "${id}: ${title}"}

When I run this, I get the following results, i.e. item 2 is not removed as expected

  allButThis ...
  all is [1: Issue-1, 2: Issue-2, 3: Issue-3]
  all with 2 removed: [1: Issue-1, 2: Issue-2, 3: Issue-3]

As far as I can tell, this remove should work, per e.g. http://groovy.codehaus.org/JN1035-Maps, where the "remove" is described one third down the page.

Estoy usando Grails 1.3.7.

Muchas Gracias

P.S. I added my toString() method (above), perhaps I fooled myself.

------------- update ----------

I removed my toString() method, and followed Rob's solution, namely:

  all.remove(this)
  println "all with ${this} removed: ${all}"

que produce:

 all is [momentum.Issue : 1, momentum.Issue : 2, momentum.Issue : 3]
 all with momentum.Issue : 2 removed: [momentum.Issue : 1, momentum.Issue : 3]

preguntado el 08 de noviembre de 11 a las 19:11

2 Respuestas

def all = Issue.list()

This is a list, not a map.

So to remove from this list:

all.remove(this)

en vez.

respondido 09 nov., 11:00

Rob, I supplemented my question (at bottom) with what you said, and it worked. Can you tell me why "this" has the value it has, as shown above? - Ray

... Apparently "this" executes to the default string method, which makes sense. Passing it into the all.remove(this) seems a bit wierd though ... certainly fooled me, that it evaluated to a string and then was passed. - Ray

... I should say the "this" reference, passed into the remove() on the list, was converted to its String form (by executing toString()). - Ray

Lists get a nice toString, so when you did "${all}" it called toString behind the scenes, which calls toString on each element member. - Rob Elsner

this.id es de tipo Long and therefore, if you want to remove the n'th item, you need to convert it to an integer. however this is highly dangerous since the id's entry is not always the n'th entry. remove this item using .findAll({it.id != this.id}) would be more save.

In this case, I would recommend you to do it like this:

def allExceptThis = Issue.withCriteria {
   ne("id", this.id)
}.list();

respondido 09 nov., 11:00

Thanks Crudolf. I'm a little confused about the ".findAll" being more safe, but then you recommended the .withCriteria. Could you please expand? - Ray

sorry for confusion: its not more safe to use withCriteria en lugar de findAll. But I would exclude "this" not on the software layer but on the database layer. Therefore you need to create a query, which excludes the object with the same id. I like withCriteria more than the findAll conditions in this case. Note, that doing like above you do not need to manipulate the collections afterwards anymore! - Chris

Crudolf, this makes sense to me -- to do it at the database layer. But still not clear why you like the .withCriteria better than .findAll, which I'd like to understand. I'm happy to use .withCriteria, would just like to understand why it's different than findAll. Is it just a clearer way to do the code, is that why you like it better? Thanks - Ray

withCriteria will prepare and execute a SQL query. findAll is part of the collection API and will filter on the software layer (on an existing collection). - Chris

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.