How to iterate over a list of type Class to edit the properties of its objects in Groovy - loops

I know there are more elaborate ways to achieve this in Java, but Groovy should have a concise way to do the same as per http://groovy.codehaus.org/Looping
Class Currency.groovy
class Currency {
String name
double rate
}
CurrencyController
def select(){
List<Currency> selectedCurrencies = Currency.getAll(params.currencies)
selectedCurrencies.eachWithIndex { obj, i -> obj.rate = update(obj.name)};
[selectedCurrencies:selectedCurrencies]
}
def update(String sym){
return sym
}
The above code throws:
No signature of method: currencychecker.CurrencyController$_$tt__select_closure12.doCall() is applicable for argument types: (currencychecker.Currency)

Thanks to #dmahapatro, the issue was that I was using an iterator variable obj[i], even though obj itself is the iterated object. The rest is correct!
I experimented with selectCurrencies.each as well instead of selectCurrencies.eachWithIndex however the right one in this case is eachWithIndex

Related

How to get ID's from JSON array in groovy using the each method?

I'm trying to get a list of ID's from a JSON array in Groovy. I know how to get the ID's using the regular FOR loop, but I would like to know how to do the same with the each method. I'm not sure how to implement that. Does anyone have any idea?
Thank you in advance. Here's my code that works just fine using the regular for loop. However I would like to do it with the each method.
import groovy.json.*
def restresponse = '[{"id":5, "name":"Bob"},{"id":8, "name":"John"},{"id":12, "name":"Jim"},{"id":20, "name":"Sally"}]'
def json = new JsonSlurper().parseText(restresponse)
def myListOfIDs = []
for (int i = 0; i < json.size; i++) {
myListOfIDs.add(json[i].id) // getting all ID's for each SourceSystem
}
log.info(myListOfIDs) // This prints out all this IDs
The shortest way to perform this "conversion" is by using the Groovy's Collection collect method, e.g.:
def myListOfIDs = json.collect { ele -> ele.id }
EDIT: As pointed out by #dmahapatro there's an even shorter possibility:
def myListOfIDs = json*.id

JSON parse and encoding with generic types

I have an generic array of objects:
static Array<Level> allLevels = new Array<Level>();
Now I want to encode it to json like this:
Json json = new Json();
String levelsJsonString = json.prettyPrint(allLevels);
The problem occurs when I'm trying to reverse this process:
allLevels = json.fromJson(Level.class, levelsJsonString);
It is raising that Array and Level are incompatible types. How to do this?
As far as I know there's always problem with passing generic type class to a json fromJson() method.
The simpliest workarround is just to wrap Array type like:
public class Levels
{
public static Array<Level> allLevels = new Array<Level>();
}
Then you can use it just like
Levels.allLevels.add( new Level() ); //etc...
and retrieve it from JSON like
... = json.fromJson(Levels.class, jsonLevels);
passing the wrapping class class object to fromJson method. The same you are doing hen converting to JSON - pass wrapping class not just Array object
String levelsJsonString = json.prettyPrint(Levels.allLevels);

get classOf[Array[A]] from classOf[A]

I have a list of scala classes in the form like:
List(classOf[A], classOf[B], ...)
I need to register these classes as well as the array of the classes into kryo. The result is like:
kryo.register(classOf[A])
kryo.register(classOf[Array[A]])
kryo.register(classOf[B])
kryo.register(classOf[Array[B]])
...
So, with the list at hand, I may just use a foreach to register both the class and the array of the class.
However, I fail to get classOf[Array[A]] from classOf[A]. I have tried the ClassTag as following method:
def getArrayClass[T: ClassTag](c: Class[T]): Class[_] = {
classOf[Array[T]]
}
The result is not the right (though the type of the both results is the same), and kryo still complains that Class is not registered: A[].
scala> getArrayClass(classOf[A])
res0: Class[Array[A]] = class java.lang.Object
scala> classOf[Array[A]]
res1: Class[Array[A]] = class [LA;
Any clues? Thanks.
You can do it using the wrap method ClassTag:
def getArrayClass(c: Class[_]): Class[_] =
scala.reflect.ClassTag(c).wrap.runtimeClass
Note that this does not work if c is classOf[Null] or classOf[Nothing] (I believe this is bug in ClassTags). For any other Class, it will work.
You can also go to the Java way of doing it, without ClassTags, which is basically equivalent:
def getArrayClass(c: Class[_]): Class[_] =
java.lang.reflect.Array.newInstance(c, 0).getClass

Tuple case mapping don't work with generic Array[T] in scala

I don't understand why the compiler cannot understand the case instruction mapping on tuple when i try to use with generics Array[T].
class Variable[T](val p: Prototype[T], val value: T)
class Prototype[T](val name: String)(implicit m: Manifest[T])
// Columns to variable converter
implicit def columns2Variables[T](columns:Array[(String,Array[T])]): Iterable[Variable[Array[T]]] = {
columns.map{
case(name,value) =>
new Variable[Array[T]](new Prototype[Array[T]](name), value)
}.toIterable
}
Error say :
error: constructor cannot be instantiated to expected type;
found : (T1, T2)
required: fr.geocite.simExplorator.data.Variable[Array[T]]
case(name,value) =>
I'm also not sure about the wording of the error, but first of all, you will need the manifest for T because it is required for constructing new Prototype[Array[T]] (the array manifest can be automatically generated if a manifest for its type parameter is in scope).
Is there any reason you absolutely need arrays? They come with the irregularity of Java's type system, they are mutable, and they offer very little advantage over for example Vector. Lastly, and that's probably why carry around the manifests, unlike arrays standard collections do not require manifests for construction.
class Variable[T](val p: Prototype[T], val value: T)
class Prototype[T](val name: String)
implicit def cols2v[T](cols: Vector[(String,Vector[T])]): Vector[Variable[Vector[T]]] =
cols.map {
case (name, value) => new Variable(new Prototype(name), value)
}

Creating an array of properties of items in an existing array

Probably not the best title, but I'll explain:
I have an array of objects - lets call them Person.
Each Person has a Name. I want to create an array of Name respectively.
Currently I have:
def peopleNames = new ArrayList<String>()
for (person in people)
{
peopleNames.add(person.name)
}
Does groovy provide a better means of doing so?
Groovy provides a collect method on Groovy collections that makes it possible to do this in one line:
def peopleNames = people.collect { it.name }
Or the spread operator:
def peopleNames = people*.name
The most concise way of doing this is to use a GPath expression
// Create a class and use it to setup some test data
class Person {
String name
Integer age
}
def people = [new Person(name: 'bob'), new Person(name: 'bill')]
// This is where we get the array of names
def peopleNames = people.name
// Check that it worked
assert ['bob', 'bill'] == peopleNames
This is one whole character shorter than the spread operator suggestion. However, IMO both the sperad operator and collect{} solutions are more readable, particularly to Java programmers.
Why don't you try this? I like this one because it's so understandable
def people = getPeople() //Method where you get all the people
def names = []
people.each{ person ->
names << person.name
}

Resources