I'm not sure why, but I can't sort my collection by a nested attribute in my collection. Below is a screenshot of the collection. I can successfully sort by an attribute like "title" as seen below, but not by a nested attribute like ratings.critics_rating or ratings.audience_score. When I try to log out a or b for the nested attributes, I get "undefined".
This works:
comparator: (a, b) ->
log 'comparing'
a = a.get('title') ## works
b = b.get('title') ## works
return 0 if a is b
if a > b then 1 else -1
This doesn't
comparator: (a, b) ->
log 'comparing'
a = a.get('ratings.critics_rating') ## doesnt work
b = b.get('ratings.critics_rating') ## doesnt work
...
Model.get accesses the attributes on the model but doesn't try to access nested attributes : a.get('ratings.critics_rating') is equivalent to a.attributes['ratings.critics_rating'] and that's not what you want.
Try a.get('ratings').critics_rating instead,
comparator: (a, b) ->
log 'comparing'
a = a.get('ratings').critics_rating
b = b.get('ratings').critics_rating
And a demo http://jsfiddle.net/nikoshr/4Lzx1vw5/
Related
List<EPosition> has S and P role.
For some employee, P role exists but now S does not exists.
So Source will only provide P but not S row in list.
In Database, WE have both P as well as S.
We want to make all S row as NULL (do not delete). So how to compare two lists
List<EPosition> src; //Fetch from Soap
List<EPosition> db;//Fetch from DB
for (EPosition d: db){
for (Eposition s: src){
if (s.ID = d.ID){
//Make it null
}
}
}
merge later
Problem statement: From the problem statement, what I understood is you have two lists (say A and B), where A contains some objects which are also present in B and you want to set this value to null in A using java streams.
Solution: So to do that you need to use the map on stream where each object is mapped to null if you find the object in B else object itself. To find whether the object is present in B there are two ways :
a. use contains method of the list (this will use equals method of the object in your case Eposition)
dbs = dbs.stream()
.map(db -> return src.contains(db) ? null :db)
.collect(Collectors.toList());
b. simply iterate over second list using stream and find a match of the id using anyMatch function.
dbs = dbs.stream()
.map(db -> return src.stream().anyMatch(sid -> sid.ID.equals(did.ID) ? null :db)
.collect(Collectors.toList());
I have a list of objects and I would like to compare them by ids field. However, I would like to item with id=3 to show first, and then id=0, id=1 and so on.
list = list.sortedWith(compareBy<MyItem> {it.id})
I was trying a lot of combinations but don't know where to add if statement.
Greetings
list = list.sortedWith(Comparator { a, b -> when {
a.id == 3 -> -1
b.id == 3 -> 1
else -> Integer.compare(a.id, b.id)
}})
Given a function f:ValueA -> ValueB, how could I map an IGrouping of type IGrouping<Key, ValueA> to IGrouping<Key, ValueB>?
Problem instance:
Say you have this type:
TaggedItem = { Tag:Tag ; Item:Item }
and this query:
query {
for i in taggedItems
groupBy i.Tag into g
select g
}
This would give you a seq of type: IGrouping<Tag, TaggedItem>, but I really want a seq of type: IGrouping<Tag, Item>.
The mapping function is: fun taggedItem -> taggedItem.Item
Solution
The solution is to avoid the mapping of groupings and instead do the transformation while doing the group, using groupValBy, as pointed by the selected answer. The selected answer also shows how to do the mapping from one type of grouping to the other, if you insist.
query {
for i in taggedItems
groupValBy i.Tag i.Item into g
select g
}
How about this?
let mapGrouping f (xs : IGrouping<_,_>) =
let projection = xs |> Seq.map (fun x -> xs.Key, f x)
(projection.GroupBy (fst, snd)).First()
From your code example, I think you want this:
query {
for i in taggedItems do
groupValBy i.Item i.Tag into g
select g
}
At https://msdn.microsoft.com/en-us/library/hh225374.aspx, we learn that groupValBy "selects a value for each element selected so far and groups the elements by the given key."
I have a given list of data :
def given = [
[Country:'Japan',Flag:'Yes',Event:'New Year'],
[Country:'china',Flag:'No',Event:'Spring Festival'],
[Country:'uk',Flag:'No',Event:'National Holiday'],
[Country:'us',Flag:'Yes',Event:'Labour Day'],
[Country:'us',Flag:'Yes',Event:'New Year'],
[Country:'uk',Flag:'Yes',Event:'Memorial Day']
]
I can sort using groovy sort method :
given = given.collect().sort { a, b ->
a.Flag <=> b.Flag ?: a.Event <=> b.Event
}
but, how would i do it if the sort by is mentioned by user and stored in separate list like
eg : def sortOrder = ["Country","Flag"], Here sort Order is dynamic that is users choice : ["Country","Flag"] / ["Country","Flag","Event"] or none. How can i write sort method so that it takes my dynamic arguments in closure ?
Assuming you have your custom order in a variable order, try
given.sort { a, b ->
order.inject(0) { o, e ->
o ?: a[e] <=> b[e]
}
}
One way would be to iterate the sortorder and use findResult to get the "ufo" results. The ugly part about this, is that findResults does not use groovy truth and sort needs an int, so some elvis action is needed to. e.g.
def given = [[Country:'Japan',Flag:'Yes',Event:'New Year'],
[Country:'china',Flag:'No',Event:'Spring Festival'],
[Country:'uk',Flag:'No',Event:'National Holiday'],
[Country:'us',Flag:'Yes',Event:'Labour Day'],
[Country:'us',Flag:'Yes',Event:'New Year'],
[Country:'uk',Flag:'Yes',Event:'Memorial Day']]
def sortorder = ['Flag', 'Event']
assert given.sort{ a,b ->
sortorder.findResult{ a[it] <=> b[it] ?: null } ?: 0
}.first()==[Country:'uk', Flag:'No', Event:'National Holiday']
I'm learning Apache Pig and have encountered an issue to realise what I wish.
I've this object (after doing a GROUP BY):
MLSET_1: {group chararray,MLSET: {(key: chararray, text: chararray)}}
I'd like to GENERATE key only when a certain pattern (PATTERN_A) appears in text AND another pattern (PATTERN_B) does not appear in the text field for one key.
I know that I can use MLSET.text to get a tupple of all text values for a specific key but then I'm still having the same issue on how to filter on the list of items from a tuple.
Here's an example:
(key_A,{(key_A,start),(key_A,stop),(key_A,unknown),(key_A,whatever)})
(key_B,{(key_B,stop),(key_B,whatever)})
(key_C,{(key_C,start),(key_C,stop),(key_C,whatever)})
I'd like to get keys for lines where "start" appears and "unknown" does not appears. In this example I will get only key_C as a result.
Thanks in advance for your help !
Here's some code that might help you out. The solution is a nested foreach here:
C = FOREACH MLSET_1 {F1 = FILTER MLSET BY (text == PATTERN_A); F2 = FILTER MLSET BY (text != PATTERN_B); GENERATE group, COUNT(F1) AS cnt1, COUNT(F2) AS cnt2;};
D = FILTER C BY (cnt1 > 1 AND cnt2 == 0);
you'll probably have to adapt the comparison in the nested filter.
Here the another approach
C = FOREACH MLSET_1 GENERATE $0,$1,BagToString(MLSET.(key,text));
D = FILTER C BY ($2 MATCHES '.*start.*') AND NOT($2 MATCHES '.*unknown.*');
E = FOREACH D GENERATE $0,$1;
DUMP E;
Output for the above input:
(key_c,{(key_c,start),(key_c,stop),(key_c,whatever)})