Query: how can i pull minimum value from a map in Grails
So far i have found following code to get minimum value from a map in groovy
["Java":1, "Groovy":4, "JavaScript":2].min{it.value}
but it donot work in Grails
i have tried following piece of code
def map = ["Java":1, "Groovy":4, "JavaScript":2]
println map.min{it.value}
assert map.min{it.value}==1
Thanks in advance
If you want the minimum value from the map, you can do:
def map = ["Java":1, "Groovy":4, "JavaScript":2]
println map.values().min()
assert map.values().min() == 1
edit
Also, the closure accepting version of map.min has been in Groovy since 1.7.6, and Grails (as of v1.3.6) uses Groovy 1.7.5
min() doesn't return a minimum value returned by argument closure, it returns the element of a collection for which the closure returns minimum.
map.min {it.value} is valid call, but it's not a value. It's a MapEntry, with key and value properties. So map.min{it.value}.value would do.
Related
I have a problem with mapping in Groovy.
I would like to get a value based on a variable.
def function(){
map = [
'test1': '1234',
'test2': '4567'
]
var=test1
def result = map.get.("$var")
return result
}
But, unfortunately. I always get back:
Cannot get property '[test1]' on null object
You are making a HashMap behind the scenes here and the way you are accessing it map.get.["$var"] Groovy is trying to access a key called "get" on your variable map.
You just want map[var]
Updated with BalRog's note below
I am using Jedis. I need a Lua script to scan for a pattern with a specified limit. I don't know how to pass the parameters inside Lua script.
Sample Code:
String script="return {redis.call('SCAN',KEYS[1],'COUNT',KEYS[2],'MATCH',KEYS[3]}";
List<String> response = (List<String>)jedis.eval(script,cursor,COUNT,pattern);
How do I pass these parameters to the script?
Your code has several points to fix.
In scan command, 'match' parameter should be placed prior to 'count'.
You should only use KEYS when it is a place for Redis key. Other things should be represented to ARGV.
You forgot to specify key count while calling Jedis.eval().
So, fixed version of your code is,
String script="return {redis.call('SCAN',ARGV[1],'MATCH',ARGV[2],'COUNT',ARGV[3])}";
List<String> response = (List<String>)jedis.eval(script, 0, cursor, pattern, COUNT);
But I agree Itamar to use Jedis.scan() instead.
Hope this helps.
question from a groovy newbie:
sql is initiated as follows
final Binding binding = new Binding();
binding.setProperty("sql", sql);
final groovy.sql.Sql sql = Sql.newInstance(dbConfig.getUrl(), dbConfig.getUserName(), dbConfig.getPasswd(),"oracle.jdbc.OracleDriver");
I am running a query in groovy like this
def listOfRows = sql.rows (select column1 from table1);
listOfRows when printed shows contents like [[column1_name:value1], [column1_name:value2], [column1_name:value3]]
I want to check if value2 (a String) exists in the returned list of values from the above query.
I have tried doing listOfRows.contains('value2') and listOfRows.find('value2'),
it complains that the method does not exist for lists..
what's the best way of doing this ?
EDITED: I have corrected the list of printed values. What's being returned is List<GroovyResultSet>
and I have also added the definition of sql.
I would suggest you to take a look at groovy documentation, and particularly to collections documentation (both tutorial and JDK/GDK).
in that case, the most specifically adapted solution would be to use Collection#find() ... with something like
listOfRows.find { it.contains(':value2') }
Which can be translated into human-readable
find the first element in this collection which string contains ":value2".
You probably want
listOfRows.column1.contains( 'value2' )
You are probably invoking this method which takes a GString (note that GString != String) as an argument. According to this question, a string in single quotes is a standard java string, and a string in double quotes is a templatable string.
'hello' //java.lang.String
"hello" //groovy.lang.GString
Try this:
listOfRows.contains("value2")
what i ended up doing is following :
iterate the listOfRows, get all the values for column1 from each GroovyResultSet into a listOfValues ,then check for my values in that list.
def listOfValues=[];
listOfRows.collect(listOfValues){it.getAt('column1')};
if(listOfValues.size()==3){
println('success');
}
I have requirement in which i need some logic of criteria query to be config driven. Earlier i used to query like :
e.g.:
User.createCriteria().list{
or{
eq('username',user.username)
eq('name',user.name)
}
}
But, i need this to be configurable in my use case so, i try this code snippet.
def criteriaCondition= grailsApplication.config.criteriaCondition?:{user->
or{
eq('username',user.username)
eq('name',user.name)
}
}
User.createCriteria().list{criteriaCondition(user)}
But, This doesn't work for me. I am getting missing method exception for "or" I tried few solution from some sources but it didn't worked for me.
So, can anyone help me :
1) How to make the above given code work.
2) Any other better way for my use case.
Thanks in advance!!!
you have to pass criteriaBuilder object to the closure, something like this:
def criteriaCondition = grailsApplication.config.criteriaCondition ?: { cb, user ->
cb.or{
cb.eq('username',user.username)
cb.eq('name',user.name)
}
}
def criteriaBuilder = User.createCriteria()
criteriaBuilder.list{
criteriaCondition(criteriaBuilder, user)
}
obviously, closure in the Config.groovy also has to have the same parameters list, including cb
The way the criteria builder mechanism works, the list method expects to be passed a closure which it will call, whereas your current code is calling the criteriaCondition closure itself rather than letting the criteria builder call it. "Currying" will help you here: given
def criteriaCondition= grailsApplication.config.criteriaCondition?:{user->
or{
eq('username',user.username)
eq('name',user.name)
}
}
instead of saying
User.createCriteria().list{criteriaCondition(user)}
you say
User.createCriteria().list(criteriaCondition.curry(user))
(note the round brackets rather than braces).
The curry method of Closure returns you another Closure with some or all of its arguments "pre-bound" to specific values. For example
def add = {a, b -> a + b}
def twoPlus = add.curry(2) // gives a closure equivalent to {b -> 2 + b}
println twoPlus(3) // prints 5
In your case, criteriaCondition.curry(user) gives you a zero-argument closure that you can pass to criteria.list. You can curry as many arguments as you like (up to the number that the closure can accept).
In a controller I have this finder
User.findByEmail('test#test.com')
And works.
Works even if I write
User.findByEmail(null)
But if i write
User.findByEmail(session.email)
and session.email is not defined (ergo is null) it throw exception
groovy.lang.MissingMethodException: No signature of method: myapp.User.findByEmail() is applicable for argument types: () values: []
Is this behavior right?
If i evaluate "session.email" it give me null so I think it must work as it do when I write
User.findByEmail(null)
Even more strange....
If I run this code in groovy console:
import myapp.User
User.findByEmail(null)
It return a user that has null email but if I run the same code a second time it return
groovy.lang.MissingMethodException: No signature of method: myapp.User.findByEmail() is applicable for argument types: () values: []
You can't use standard findBySomething dynamic finders to search for null values, you need to use the findBySomethingIsNull version instead. Try
def user = (session.email ? User.findByEmail(session.email)
: User.findByEmailIsNull())
Note that even if User.findByEmail(null) worked correctly every time, it would not necessarily give you the correct results on all databases as a findBySomething(null) would translate to
WHERE something = null
in the underlying SQL query, and according to the SQL spec null is not equal to anything else (not even to null). You have to use something is null in SQL to match null values, which is what findBySomethingIsNull() translates to.
You could write a static utility method in the User class to gather this check into one place
public static User byOptEmail(val) {
if(val == null) {
return User.findByEmailIsNull()
}
User.findByEmail(val)
}
and then use User.byOptEmail(session.email) in your controllers.
Jeff Brown from grails nabble forum has identified my problem. It's a GORM bug. see jira
More info on this thread
This jira too
I tried with debugger and it looks it should be working, as you write. Maybe the groovy itself is a little bit confused here, try to help it this way:
User.findByEmail( session['email'] )