How to use a SplayTreeMap on Firebase snapshot dictionary in dart/Flutter? - sorting

I'm successfully getting data back through StreamBuilder and need to sort it. How can I sort a Map of my snapshot data by keys? Also, If you give an example of doing this my value that would help also. I think I want to do a SplayTreeMap, but if there is a better way please provide. Here is my dictionary...
{Vid2: {imageString: https://i.ytimg.com/vi/Amq-qlqbjYA/mqdefault.jpg, title: BLACKPINK - '마지막처럼 (AS IF IT'S YOUR LAST)' M/V, rank: 2, videoID: Amq-qlqbjYA}, Vid10: {imageString: https://i.ytimg.com/vi/KSH-FVVtTf0/mqdefault.jpg, title: EXO 엑소 'Monster' MV, rank: 10, videoID: KSH-FVVtTf0}, Vid6: {imageString: https://i.ytimg.com/vi/BVwAVbKYYeM/mqdefault.jpg, title: [MV] BTS(방탄소년단) _ DOPE(쩔어), rank: 6, videoID: BVwAVbKYYeM}, Vid3: {imageString: https://i.ytimg.com/vi/m8MfJg68oCs/mqdefault.jpg, title: [MV] BTS(방탄소년단) _ Boy In Luv(상남자), rank: 3, videoID: m8MfJg68oCs}, Vid4: {imageString: https://i.ytimg.com/vi/9pdj4iJD08s/mqdefault.jpg, title: BLACKPINK - '불장난 (PLAYING WITH FIRE)' M/V, rank: 4, videoID: 9pdj4iJD08s}, Vid1: {imageString: https://i.ytimg.com/vi/3s1jaFDrp5M/mqdefault.jpg, title: EPIK HIGH - 'BORN HATER' M/V, rank: 1, videoID: 3s1jaFDrp5M}, Vid8: {imageString: https://i.ytimg.com/vi/3QAcvc4Ysl0/mqdefault.jpg, title: LONNI - LA KPOP 2, rank: 8, videoID: 3QAcvc4Ysl0}, Vid5: {imageString: https://i.ytimg.com/vi/2ips2mM7Zqw/default.jpg, title: BIGBANG - 뱅뱅뱅 (BANG BANG BANG) M/V, rank: 5, videoID: 2ips2mM7Zqw}}
I would like to display it either by keys...
Vid1, Vid2, Vid3...
or by values like rank ie...
Vid1:rank "1", Vid2: rank "2", Vid3: rank "3"...

If the source is a map, this should do what you want:
final sorted = new SplayTreeMap<String,dynamic>.from(map, (a, b) => a.compareTo(b));
DartPad example

Related

Iterate through a child map in a for loop in groovy

Let us assume I have a map like below which contains another map (child map) within it. I like to print the child map as individual rows for each key.
def map =[
1: [
[name:"Jerry", age: 42, city: "New York"],
[name:"Long", age: 25, city: "New York"]
],
2: [
[name:"Dustin", age: 29, city: "New York"],
[name:"Bob", age: 34, city: "New York"]
]
]
Currently, I iterate through the parent map, and am able to print the names. But, that is not actually what I want. I wanted to see if I can atleast iterate through the parent map. I do not see errors so far.
for(allentries in map){
loggerApi.info("${allentries.key}: ${allentries.value.name}") // this prints [Jerry, Long] for key 1 & [Dustin, Bob] for key 2
loggerApi.info("${allentries.key}: ${allentries.value.age}")
loggerApi.info("${allentries.key}: ${allentries.value.city}")
}
Can you please let me know what I should add to the above code to see individual rows like these:
Name Age City
Jerry 42 New York
Long 25 New York
Dustin 29 New York
Bob 34 New York
Appreciate.
Thank you.
Br,
Noor.
Assuming you got the input structure wrong in the question, and you have a list of maps inside each value in map, you can just iterate through them in an internal loop
​def map =[
1: [
[name:"Jerry", age: 42, city: "New York"],
[name:"Long", age: 25, city: "New York"]
],
2: [
[name:"Dustin", age: 29, city: "New York"],
[name:"Bob", age: 34, city: "New York"]
]
]
map.each { key, value ->
value.each { submap ->
println "$key $submap.name $submap.age $submap.city"
// Or with no prefixing number:
// println "$submap.name $submap.age $submap.city"
}
}

PouchDB: filtering, ordering and paging

Very similar to these two CouchDB questions: 3311225 and 8924793, except that these approaches don't allow partial matching. Having e.g. these entries:
[{_id: 1, status: 'NEW', name: 'a'},
{_id: 2, status: 'NEW', name: 'aab'},
{_id: 3, status: 'NEW', name: 'ab'},
{_id: 4, status: 'NEW', name: 'aaa'},
{_id: 5, status: 'NEW', name: 'aa'}]
and key
[status, name, _id]
There seems to be no way to
filter these entries by status (full string match) and name (partial string match ~ startsWith)
order them by id
paginate them
because of the partial string match on name. The high value unicode character \uffff that allows this partial match also causes to ignore the _id part of the key, meaning the resulting entries are not sorted by _id, but rather by status and name.
var status = 'NEW';
var name = 'aa'
var query = {
startkey: [status, name],
endkey: [status, name + '\uffff', {}],
skip: 0,
limit: 10
};
results in
[{_id: 5, status: 'NEW', name: 'aa'},
{_id: 4, status: 'NEW', name: 'aaa'},
{_id: 2, status: 'NEW', name: 'aab'}]
There is no option to sort in memory, as this would only sort the individual pages, and not the entire data set. Any ideas about this?

ActiveRecord: Unique by attribute

I am trying to filter ActiveRecord_AssociationRelations to be unique by parent id.
So, I'd like a list like this:
[#<Message id: 25, posted_by_id: 3, posted_at: "2014-10-30 06:02:47", parent_id: 20, content: "This is a comment", created_at: "2014-10-30 06:02:47", updated_at: "2014-10-30 06:02:47">,
#<Message id: 23, posted_by_id: 3, posted_at: "2014-10-28 16:11:02", parent_id: 20, content: "This is another comment", created_at: "2014-10-28 16:11:02", updated_at: "2014-10-28 16:11:02">]}
to return this:
[#<Message id: 25, posted_by_id: 3, posted_at: "2014-10-30 06:02:47", parent_id: 20, content: "This is a comment", created_at: "2014-10-30 06:02:47", updated_at: "2014-10-30 06:02:47">]
I've tried various techniques including:
#messages.uniq(&:parent_id) # returns the same list (with duplicate parent_ids)
#messages.select(:parent_id).distinct # returns [#<Message id: nil, parent_id: 20>]
and uniq_by has been removed from Rails 4.1.
Have you tried
group(:parent_id)
It sounds to me like that is what you are after. This does return the first entry with the given parent_id. If you want the last entry you will have to reorder the result in a subquery and then use the group.
For me in Rails 3.2 & Postgresql, Foo.group(:bar) works on simple queries but gives me an error if I have any where clauses on there, for instance
irb> Message.where(receiver_id: 434).group(:sender_id)
=> PG::GroupingError: ERROR: column "messages.id" must appear in the
GROUP BY clause or be used in an aggregate function
I ended up specifying an SQL 'DISTINCT ON' clause to select. In a Message class I have the following scope:
scope :latest_from_each_sender, -> { order("sender_id ASC, created_at DESC").select('DISTINCT ON ("sender_id") *') }
Usage:
irb> Message.where(receiver_id: 434).latest_from_each_sender

Extract ruby hash element value from an array of objects

I've got the following array
[#<Attachment id: 73, container_id: 1, container_type: "Project", filename: "Eumna.zip", disk_filename: "140307233750_Eumna.zip", filesize: 235303, content_type: nil, digest: "9a10843635b9e9ad4241c96b90f4d331", downloads: 0, author_id: 1, created_on: "2014-03-07 17:37:50", description: "", disk_directory: "2014/03">, #<Attachment id: 74, container_id: 1, container_type: "Project", filename: "MainApp.cs", disk_filename: "140307233750_MainApp.cs", filesize: 1160, content_type: nil, digest: "6b985033e19c5a88bb5ac4e87ba4c4c2", downloads: 0, author_id: 1, created_on: "2014-03-07 17:37:50", description: "", disk_directory: "2014/03">]
I need to extract the value 73 and 74 from this string which is Attachment id.
is there any way to extract this value
just in case author meant he has an actual String instance:
string = '[#<Attachment id: 73, container_id: 1, container_type: "Project", filename: "Eumna.zip", disk_filename: "140307233750_Eumna.zip", filesize: 235303, content_type: nil, digest: "9a10843635b9e9ad4241c96b90f4d331", downloads: 0, author_id: 1, created_on: "2014-03-07 17:37:50", description: "", disk_directory: "2014/03">, #<Attachment id: 74, container_id: 1, container_type: "Project", filename: "MainApp.cs", disk_filename: "140307233750_MainApp.cs", filesize: 1160, content_type: nil, digest: "6b985033e19c5a88bb5ac4e87ba4c4c2", downloads: 0, author_id: 1, created_on: "2014-03-07 17:37:50", description: "", disk_directory: "2014/03">]'
string.scan(/\sid: (\d+)/).flatten
=> ["73", "74"]
Do as below using Array#collect:
array.collect(&:id)
In case it is a string use JSON::parse to get the array back from the string first, then use Array#collect method as below :
require 'json'
array = JSON.parse(string)
array.collect(&:id)
The elements of the array (I'll call it a) look like instances of the class Attachment (not strings). You can confirm that by executing e.class in IRB, where e is any element a (e.g., a.first). My assumption is correct if it returns Attachment. The following assumes that is the case.
#Arup shows how to retrieve the values of the instance variable #id when it has an accessor (for reading):
a.map(&:id)
(aka collect). You can see if #id has an accessor by executing
e.instance_methods(false)
for any element e of a. This returns an array which contains all the instance methods defined for the class Attachment. (The argument false causes Ruby's built-in methods to be excluded.) If #id does not have an accessor, you will need to use Object#instance_variable_get:
a.map { |e| e.instance_variable_get(:#id) }
(You could alternatively write the argument as a string: "#id").
If
s = '[#<Attachment id: 73, container_id: 1,..]'
in fact a string, but you neglected to enclose it in (single) quotes, then you must execute
a = eval(s)
to convert it to an array of instances of Attachment before you can extract the values of :#a.
Hear that 'click'? That was me starting my stop watch. I want to see how long it will take for a comment to appear that scolds me for suggesting the use of (the much-maligned) eval.
Two suggestions: shorten code to the essentials and avoid the need for readers to scroll horizontally to read it. Here, for example, you could have written this:
a = [#<Attachment id: 73, container_id: 1>, #<Attachment id: 74, container_id: 1>]
All the instance variables I've removed are irrelevant to the question.
If that had been too long to fit on one lines (without scrolling horizontally, write it as:
a = [#<Attachment id: 73, container_id: 1>,
#<Attachment id: 74, container_id: 1>]
Lastly, being new to SO, have a look at this guide.

Get Unique contents from Ruby Hash

I have a Hash #estate:
[#<Estate id: 1, Name: "Thane ", Address: "Thane St.", created_at: "2013-06-21 16:40:50", updated_at: "2013-06-21 16:40:50", user_id: 2, asset_file_name: "DSC02358.JPG", asset_content_type: "image/jpeg", asset_file_size: 5520613, asset_updated_at: "2013-06-21 16:40:49", Mgmt: "abc">,
#<Estate id: 2, Name: "Mumbai", Address: "Mumbai St.", created_at: "2013-06-21 19:13:59", updated_at: "2013-06-21 19:14:28", user_id: 2, asset_file_name: "DSC02359.JPG", asset_content_type: "image/jpeg", asset_file_size: 5085580, asset_updated_at: "2013-06-21 19:13:57", Mgmt: "abc">]
Is it possible to make new Hash with unique values according to the user_id: 2, because currently 2 elements have the user_id same i.e 2, I just want it once in the hash, what should I do ?
It seems to be something like a has_many relation between User model and Estate model, right? If I understood you correctly, than you need in fact to group your Estate by user_id:
PostgreSQL:
Estate.select('DISTINCT ON (user_id) *').all
MySQL:
Estate.group(:user_id).all
P.S. I'd not recommend to select all records from a database and then process them with Ruby as databases handle operations with data in much more efficient way.
Here is an sample example to get you a good start:
h = [ { a: 2, b: 3}, { a: 2, c: 3 } ]
h.uniq { |i| i[:a] }
# => [{:a=>2, :b=>3}]

Resources