[groovy-user] list of maps, is there a way to get unique

1,046 views
Skip to first unread message

Joe Greenawalt

unread,
Apr 1, 2010, 11:10:53 PM4/1/10
to us...@groovy.codehaus.org
Hi, I have a very large List of Maps that i'm going to have process.

I was looking through GDK and found this to work great:

def listOfMaps = [["id":"1","name":"joe"],["id":"2","name":"bob"],["id":"1","name":"steve"]]
def x = listOfMaps.findAll{it.get("id")=="1"}
assert x == [[id:1, name:joe], [id:1, name:steve]]

So i thought if there was a Groovy way to get a list of (distinct) unique values for id: e.g. [1,2], without going through an each; that would be absolutely fantastic.

Nothing seemed to jump out at me, any thoughts?

Thanks,
Joe

Paul King

unread,
Apr 1, 2010, 11:41:20 PM4/1/10
to us...@groovy.codehaus.org
On 2/04/2010 1:10 PM, Joe Greenawalt wrote:
> def listOfMaps =
> [["id":"1","name":"joe"],["id":"2","name":"bob"],["id":"1","name":"steve"]]
> def x = listOfMaps.findAll{it.get("id")=="1"}
> assert x == [[id:1, name:joe], [id:1, name:steve]]

This might be useful:

listOfMaps.groupBy{ it.id }
// => [1:[[id:1, name:joe], [id:1, name:steve]], 2:[[id:2, name:bob]]]

Cheers, Paul.


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email


Joe Greenawalt

unread,
Apr 1, 2010, 11:54:01 PM4/1/10
to us...@groovy.codehaus.org
I was just going to reply and say i found something that worked:
def map = [:]
listOfMaps.collect{map.put(it.get("id"),it.get("id"))}
println map
this gave me a unique key map, that i could then do a find all on.

However i think yours actually gives me what i want in one step rather than 2, nifty, thanks.

Peter Niederwieser

unread,
Apr 2, 2010, 1:10:55 PM4/2/10
to us...@groovy.codehaus.org

How about:

def listOfMaps =
[[id:"1",name:"joe"],[id:"2",name:"bob"],[id:"1",name:"steve"]]

def keyList = listOfMaps.collect { it.id } .unique()

// OR

def keySet = listOfMaps.collect { it.id } as Set

Cheers,
Peter

--
View this message in context: http://old.nabble.com/list-of-maps%2C-is-there-a-way-to-get-unique-tp28115650p28121029.html
Sent from the groovy - user mailing list archive at Nabble.com.

Tim Yates

unread,
Apr 2, 2010, 1:15:48 PM4/2/10
to us...@groovy.codehaus.org
Or, indeed:

def keySet2 = listOfMaps.inject( [] as Set ) { set, it -> set << it.id }

Many ways to skin a cat ;-)

Guillaume Laforge

unread,
Apr 2, 2010, 1:45:57 PM4/2/10
to us...@groovy.codehaus.org
As project lead, I'd like to publicly say we're against skinning cats, and that no animals were harmed in the process of building the Groovy project :-)
--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one

Moe

unread,
Apr 2, 2010, 2:40:08 PM4/2/10
to us...@groovy.codehaus.org
On Fri, Apr 2, 2010 at 8:45 PM, Guillaume Laforge <glaf...@codehaus.org> wrote:
As project lead, I'd like to publicly say we're against skinning cats, and that no animals were harmed in the process of building the Groovy project :-)


Hehe, Guillaume.. while we have you here.. I found another cat to skin. 
Could you please add to the println method so that it doesn't need an input?
I think people often use println "" with the " " to separate test outputs between lines use which is extremely annoying!

Anyway, 

What's wrong with just

def listOfMaps = [[id:"1",name:"joe"],[id:"2",name:"bob"],[id:"1",name:"steve"]]

listOfMaps.id == [1,2,1] // here

listOfMaps.id.unique() = [1,2]


What method is used to accomplish that behind the curtain? Is it groupBy ? 

Cheers, Moe

Btw, Guillaume... what do you think of a adding a map parameter default value option to methods. 
I find the existing default value ones rather limited, or perhaps I have missed something.

def method(def a = 10, def b = 20, def c = 30) { ... }

is there some keyword to pass to trigger for example a's default value and keep b and c?

method(Def, Def, 60) or something.  

But even better would be 

method(Map a = [a:10, b:20, c:30)  { ... }

method(a:100, c:1000, other_non_defaulted_obj:new Object(...), .... ) 

if a is passed in the method call, then the default is ignore.. otherwise it uses the default value like it will on b now... ( at least that is my intention )


Am I scoring any points here or am I just cuckoo... I am still trying to figure the answers to both? :p


Sincerely, Mohamed

Joe Greenawalt

unread,
Apr 2, 2010, 11:05:52 PM4/2/10
to us...@groovy.codehaus.org
good stuff all, thanks.

Peter Niederwieser

unread,
Apr 3, 2010, 8:41:14 AM4/3/10
to us...@groovy.codehaus.org

listOfMaps.id is short for listOfMaps*.id (the spread-dot operator), which
invokes the method/property on all list elements and returns a list of the
results. And since map elements can be accessed with property syntax, this
leads to the desired effect.

Cheers,
Peter


Moe-25 wrote:
>
> def listOfMaps =

> [[id:"1",name:"joe"],[id:"2",name:"bob"],[id:"1",name:"steve"]]
>
> listOfMaps.id == [1,2,1] // here
>
> listOfMaps.id.unique() = [1,2]
>
> What method is used to accomplish that behind the curtain? Is it groupBy ?
>

--
View this message in context: http://old.nabble.com/list-of-maps%2C-is-there-a-way-to-get-unique-tp28115650p28126715.html

Reply all
Reply to author
Forward
0 new messages