11

Is it possible to expand a map to a list of method arguments

In Python it is possible, eg. Expanding tuples into arguments

I have a def map = ['a':1, 'b':2] and a method def m(a,b)

I want to write smt like m(*map)

Community
  • 1
  • 1
Queequeg
  • 2,824
  • 8
  • 39
  • 66

3 Answers3

10

The spread operator (*) is used to tear a list apart into single elements. This can be used to invoke a method with multiple parameters and then spread a list into the values for the parameters.

List (lists in Groovy are closest related with tuples in Python1,2):

list = [1, 2]
m(*list)

Map:

map = [a: 1, b: 2]
paramsList = map.values().toList()
m(*paramsList)

An importan point is that you pass the arguments by position.

Community
  • 1
  • 1
Arturo Herrero
  • 12,772
  • 11
  • 42
  • 73
  • *you pass the arguments by position*.. what is the order of the elements in a map? – Queequeg Nov 19 '12 at 16:37
  • A map is a mapping from unique unordered keys to values, but you can emulate order by clause with sort(), see the [Map documentation](http://groovy.codehaus.org/JN1035-Maps) – Arturo Herrero Nov 19 '12 at 20:07
  • 2
    I understand how maps work, but some are ordered, some not, some are sorted, some not. For instance: if I have a method `def m(a,b)` and a map `def map = [b:1, a:2]` then what will be the method call - `m(1,2)` or `m(2,1)` or undefined...... – Queequeg Nov 20 '12 at 13:56
  • I'm not sure. I think that if you have a map `def map = [b:1, a:2]` the method call is `m(1,2)` but the implementation could change in the future, it's depend on the data structures used under the hood. Groovy documentation says that a map is an unordered keys to values. You can learn more about this topic here: [Sorted maps in groovy](http://stackoverflow.com/q/13410551/462015) – Arturo Herrero Nov 20 '12 at 15:08
  • OK. So basically, what I need is currently unavailable in groovy, meaning that your solution is a bit hacky... (?) – Queequeg Nov 20 '12 at 15:35
  • 1
    Is the same case as [dictionaries in Python](http://docs.python.org/3.3/tutorial/datastructures.html#dictionaries): _dictionary returns a list of all the keys used in the dictionary, in arbitrary order (if you want it sorted, just use sorted(d.keys()) instead)_ – Arturo Herrero Nov 20 '12 at 16:18
  • Groovy looks soo much like python I almost thought this was the wrong answer ;) – J Atkin Nov 02 '15 at 22:15
1

The best I can currently think of is:

@groovy.transform.Canonical
class X {
  def a
  def b

  def fn( a, b ) {
    println "Called with $a $b"
  }
}

def map = [ a:1, b:2 ]

def x = new X( map.values().toList() )

x.fn( map.values().toList() )

However, that takes the order of the map, and not the names of the keys into consideration when calling the function/constructor.

You probably want to add a function/constructor that takes a Map, and do it that way

tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • `*map` uses the spread operator? I've seen it used only on methods like `map*.values()` How to understand the above code? – Queequeg Nov 19 '12 at 09:49
  • it gets the `values()` from the map, converts them `toList()`, and then spreads that list. Adding a brace might help you see what's going on: `new X( *(map.values().toList()) )` – tim_yates Nov 19 '12 at 09:57
  • I don't understand the use of `*map`. You can simply write `map.values().toList()` and works fine! – Arturo Herrero Nov 19 '12 at 10:05
  • @ArturoHerrero Haha, oh yeah... The `*` was superfluous :-/ – tim_yates Nov 19 '12 at 10:09
  • Spread operator doesn't work in this case: `def f(Map opts) { println("${opts}") }; f(*[a: 1, b: 2])`. The equivalent Python code works fine (you need to insert a newline instead of `;`): `def f(**kwargs): print(str(kwargs)); f(**{'a': 1, 'b': 2})` – haridsv Sep 17 '19 at 11:02
  • 1
    @haridsv the map spread operator is `*:` in groovy `f(*:[a: 1, b: 2])` – tim_yates Sep 17 '19 at 11:22
  • Thank you @tim_yates, that works! I actually meant to leave my comment on the accepted answer, so it looks out of context here and yet you still responded so I appreciate you for that. – haridsv Sep 17 '19 at 12:46
-3
   mmap = { 'a':1, 'b':2 }

   def m( a, b ):
       return a+b
   print m( **mmap )

30

3

user1755394
  • 182
  • 2
  • 7