need help removing an item from a collection of objects - groovy

I am working on a performance review application. I have a collection that tracks responses from various individuals. This particular closure will collect the scores from all the evaluations
def scores = responses.collectEntries { Category key, Collection<Response> value ->
[(key): value.score]
}
This is the structure of the value parameter, being passed in the closure
http://snag.gy/q4OEq.jpg
I am trying to remove a score from being added to the [(key):value.score]. More specifically, I'm trying to prevent someones self evaluation from being added.
I've tried several things. This being two of them.
def scores = responses.collectEntries { Category key, Collection<Response> value ->
for (i in value) {
if (i.evaluation.respondent == i.evaluation.performanceReview.employee) {
//didn't work
value.remove(i)
// also didn't work
value - i
}
}
[(key): value.score]
}
The if statement works fine, it will hit the inside conditions when there is a self evaluation. It's what's inside the if statment that doesn't work. What am I doing wrong?

Can't you get rid of the for loop and just have:
[ key,
value.findAll {
it.evaluation.respondent != it.evaluation.performanceReview.employeescore
}.score ]
As the body of the collectEntries call?

Related

How to get a value from inside Anko's async? (KotlIn)

I have a function which uses Anko's async in order to call Google's Distance API and get the distance from one location to another. unfortunately i don't know how to get the data from inside the async and pass it to another function. the code looks something like this
fun getDistance(location1:LatLng,location2:LatLng){
async{
val result = URL(url).readtext()
uithread{
//Parser
//distance value
}
}
}
I'd like to also mention im really new to kotlin or android development in general, please be kind.
There are a number of ways to tackle this; pass an object to the function with your array in it that gets rearranged in your function, or go with something like:
fun getDistance(location1 : LatLng, location2 : LatLng, f: (Long) -> Unit){
doAsync{ // Anko is deprecated as I have been made aware
val result = URL(url).readtext()
val distance : Long = // parse result
uiThread{
f(distance)
}
}
}
and call that with
getDistance(loc1, loc2) { toast("The found distance was $it") }
This is by no means the only way to go; you could update a larger-scoped variable, call a listener, put your lat-longs in a class with updating functions that are called, or a bunch of other ways that I am too lazy to think about :)

Groovy withBatch without need for closure

I am making use of withBatch API as:
int[] modifyCount = sql.withBatch(batchSize, updateQuery) { ps ->
keyValue.each { k,v ->
ps.addBatch(keyvalue:k, newvalue:v)
}
}
In closure, I set values for the placeholders in the updateQuery. It works fine.
Suppose updateQuery has already all the fields defined and hence code inside closure above is not actually needed now.
What change is needed for that?
there is no reason to use withBatch if updateQuery contains all values.
just use
sql.execute( updateQuery )
doc: http://docs.groovy-lang.org/latest/html/api/groovy/sql/Sql.html#execute(java.lang.String)

get attributes, even if they do not exist

Please don't hate me, yes I want to do something really stupid.
I want to get null on every attribute if it does not exist. I found out that I can create the propertyMissing method:
class User {
String name = "A"
}
Object.metaClass.propertyMissing() {
null
}
u = new User();
println u?.name
println u?.namee
This prints:
A
null
Now I have the "great" Hybris system in my back :D
If I add the propertyMissing part on top of my script and run this in the Hybris groovy console, I still get the MissingPropertyException.
Is there another way to avoid the MissingPropertyException exception without having to work with hundreds of try catch? (or hundreds of println u?.namee ? u.namee : null isn't working)
/Edit: 1
I have the following use case (for the Hybris system):
I want to get all necessary information in a dynamic output from some pages. Why dynamic? Some page components have the attribute headline other teaserHeadline and some other title. To avoid to create each time an try catch or if else, I created a function which loops through possible attributes and if it's null it skips that one. For that I need to return null on attributes which doesn't exist.
Here is an example which should work, but it doesn't (don't run it on your live system):
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
import de.hybris.platform.servicelayer.search.SearchResult;
flexibleSearch = spring.getBean("flexibleSearchService")
FlexibleSearchQuery query = new FlexibleSearchQuery("select {pk} from {ContentPage}");
SearchResult searchResult = flexibleSearch.search(query);
def i = 0;
def max = 1;
searchResult.result.each { page ->
if (i < max) {
gatherCMSPageInformation(page)
}
i++;
}
def gatherCMSPageInformation(page) {
page.class.metaClass.propertyMissing() {
null
}
println page.title2
}
Weird thing is, that if I run it a few times in a small interval, it starts to work. But I can't overwrite "null" to something else like "a". Also I noticed, to overwrite the Object class isn't working at all in Hybris.
/Edit 2:
I noticed, that I'm fighting against the groovy cache. Just try the first example, change null with a and then try to change it again to b in the same context, without restarting the system.
Is there a way to clear the cache?
why don't you use the groovy elvis operator?
println u?.namee ?: null

Infinite Observable to HashMap as Observable

I am still struggling with some of the basics of RxJava and would greatly appreciate some help.
I have an infinite, hot observable which emits regularly tagged events (captures in a simple class having a name (tag) and some properties). The tags are finite (in this case about 10 distinct tags) but the event specifics are every time different (a time stamp, say).
What I am trying to do now is to create a HashMap with the tags as key and the events as the entry, such that the HashMap itself becomes an infinite observable which emits the HashMap with every change.
So far, I used a Subject to subscribe to the original observable and to emit the HashMap, but I also saw the ".toMap" method. However, I cannot figure out how use that method with an infinite observable source and emit with every change. From the documentation it is not even clear to me whether this would be possible at all.
If it's not possible, is there another way, aside from using Subjects, to achieve the same? I want to keep this lean, and Subject seems rather heavy.
Here is my code convert it to a Map or Observable<Map>. But I don't know why you need to do this.
fun <T, K> Observable<T>.toInfiniteMap(keySelector: (T) -> K): Map<K, Observable<T>> {
val map = ConcurrentHashMap<K, Observable<T>>()
this.subscribeOn(Schedulers.newThread())
.doOnNext { println(it) }
.groupBy(keySelector)
.doOnNext { map.put(it.getKey(), it) }
.subscribe()
return map
}
fun <T, K> Observable<T>.toInfiniteMapObservable(keySelector: (T) -> K):
Observable<Map<K, Observable<T>>> {
val map = ConcurrentHashMap<K, Observable<T>>()
return this.subscribeOn(Schedulers.newThread())
.doOnNext { println(it) }
.groupBy(keySelector)
.doOnNext { map.put(it.getKey(), it) }
.map { map }
}

Reduce output must shrink more rapidly, what is this error about?

An user can post multiple comments in a thread, and I try to get list of threads (distinct) that an user has make comment to it, like :-
// comment table (relation table)
id, thread_id, user_id
select comment.thread_id, count(*)
from user
inner join comment on user.id=comment.user_id
where user.id = ?
group by comment.thread_id;
This is pretty easy in MySQL.
But to convert to couchdb :-
// map
function(doc)
{
emit(doc.user_id, doc.thread_id);
}
// reduce
function (key, thread_id)
{
return thread_id;
}
If I using the above map function, I will hit into an error like :-
"error": "reduce_overflow_error",
"reason": "Reduce output must shrink more rapidly: Current output: ...
I think I have applied the reduce function in wrong manner.
If using another way, like :-
// map
function (doc)
{
emit([doc.user_id, doc.thread_id], 1);
}
// reduce
function(keys, values)
{
return sum(values);
}
The group=true result is look exactly what mysql group-by does.
However, I'm unable to get ALL the list of thread by an user (given I only have the user_id during query time)
Third way, I can discard use of map reduce, and directly apply :-
emit(doc.user_id, doc.thread_id);
And do an PHP array like
foreach ( ... )
{
$threads[$thread_id] = TRUE;
}
array_keys($threads);
However, this is quite bloated and less efficient.
Second method look more accurate :-
key=[user_id, *] <-- it does not work, believe only work on exact match
key=[user_id, thread_id] <-- return one row
Is there a way to get all result without knowing the thread_id ?
(ps: I new to couchdb, and I might have describe the scenario in a bad manner)
Some reference I gotten via #jasonsmith :- http://guide.couchdb.org/draft/cookbook.html
As a rule of thumb, the reduce function should reduce to a single scalar value. That is, an integer; a string; or a small, fixed-size list or object that includes an aggregated value (or values) from the values argument. It should never just return values or similar. CouchDB will give you a warning if you try to use reduce “the wrong way”:
Follow closely to what this docs saying :-
http://wiki.apache.org/couchdb/View_Snippets#Generating_a_list_of_unique_values
// map
function(doc)
{
emit([doc.user_id, doc.thread_id], null);
}
// reduce
function (keys, values)
{
return null;
}
Query :-
?startkey=["$uid"]&endkey=["$uid",{}]&group=true
And the result now is accurate,
so the problem is lied on the reduce function and how the query being construct.

Resources