SliverChildBuilderDelegate - reverse method - list

Is there a reverse option for a SliverList like there is for ListView.builder?
I can see that the CustomScrollView has a reverse method but that doesn't help for what I'm looking for.

Since SliverList does not have a a reverse option or parameter, you'll have to calculate the reversed index by hand inside the SliverChildDelegate that's used to create the children. This would only be possible if you know the length of the list you are building.
Given you have a List, you can calculate the reversed index from SliverChildDelegate.builder's index.
(BuildContext context, int index) {
final reversedIndex = items.length - index - 1;
...
}
Here is what it looks with a SliverChildBuilderDelegate:
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
final reversedIndex = items.length - index - 1;
return MyWidget(items[reversedIndex]);
},
childCount: items.length,
),
);

Related

Kotlin: Problem with List Filter by Multiple Conditions

I'm trying to match two lists to another. In one list are items of crypto trades, the other contains so called candlesticks, which represents a price of crypto asset for one minute. A candlestick is limited by open time and close time. One trade item belongs exactly to one candlestick set. So I step through the trades list an for each item I apply a filter of two conditions. Unfortunately the filter returns no matching data. When I compare the trades data with candlestick items manually, I get a match. Here is the code of the data filter.
TradesDbHandler(dbConnector).use { dbHandler ->
val rowsInTime = dbHandler.readTimeframe(startTime, buffer)
rowsInTime.distinctBy { it.symbol }.forEach {
val symbolFilter = rowsInTime.filter { row -> row.symbol == it.symbol }
val symbolMinTime = symbolFilter.minByOrNull { it.time }
val symbolMaxTime = symbolFilter.maxByOrNull { it.time }
val tempKlines = binanceClient.getCandleSticks( symbolMaxTime!!.symbol,
symbolMinTime!!.time,
symbolMaxTime!!.time ) {
log(">>> $it")
}
val klines = mutableListOf<KlineRow>()
klines.plusElement(tempKlines.filter { row ->
(row.opentime <= it.time) &&
(row.closetime >= it.time) })
}
}
The code was not the problem but the data. Therefore no matches could be found. Thread can be closed.

AngularFire2 and Ionic2, calculating list sum

please help me to figure out how to calculate a sum of objects values coming from firebase using AngularFire2 in ionic.
I am trying do this way:
in the HTML file i want call the function:
<ion-col col-1>
{{(calculateAverage(student.$key) | async)}}
</ion-col>
In the .ts file i want to do something like this, get the list of objects, iterate over it and sum the values of a child and return that value to the html.
i know how to use this.af.database.list to get a list and show values in the HTML using the *ngFor, but not know how to iterate in the .ts file and return a value to the HTML, cause this is async.
Example of firebase data:
"-KhdUCJAyr7Y4Zz3QOnl" : {
"-KigSgGlWyFQao80DuA0" : {
"value" : "30"
},
"-KigTDI3Nue88If0fdYl" : {
"value" : "70"
}
}
Can anyong help me please?
Thanks in Advance.
You can do the calculate in subscribe of this.af.database.list.
// suppose you keep the observable
this.items = this.af.database.list('/sample');
// do calculate in observable.subscribe
this.items.subscribe(data => {
data.forEach(item => {
// sum here
calculateSum(item.value);
});
// calculate average here
calculateAverage();
});
example of how to calculate and show in templete:
sumValue = 0;
averageValue = 0;
// sum values
calculateSum(value) {
this.sumValue = this.sumValue + parseInt(value);
}
calculateAverage(count) {
this.averageValue = this.sumValue / count;
}
display result of calculate in template:
<span>averageValue</span>

Access nth item when iterating Ember object array with for rather than forEach

It made more sense in a particular case today to use a standard for (i = 0.. loop rather than a forEach, but I realised I don't know how to access objects of an Ember Array by number.
So lets say we have:
var order = this.get('order');
var orderItems = order.get('orderItems');
orderItems.forEach(function(orderItem) {
orderItem.set('price', 1000);
});
I thought I could do the equivalent as:
var order = this.get('order');
var orderItems = order.get('orderItems');
for (i = 0; i < orderItems.get('length'); i++) {
orderItems[i].set('price', 1000);
}
but I get orderItems[0] is undefined etc.
How do I access the nth element in an ember array in js?
Ember.js Array provides a objectAt method for accessing the nth element, which you can use for iteration.
Your updated code would look like :
var order = this.get('order');
var orderItems = order.get('orderItems');
for (i = 0; i < orderItems.get('length'); i++) {
orderItems.objectAt(i).set('price', 1000);
}
Check out it's documentation here: http://emberjs.com/api/classes/Ember.Array.html#method_objectAt

Map/reduce to get the count and latest date for each document grouped by key

A simple version of my document document is the following structure:
doc:
{
"date": "2014-04-16T17:13:00",
"key": "de5cefc56ff51c33351459b88d42ca9f828445c0",
}
I would like to group my document by key, to get the latest date and the number of documents for each key, something like
{ "Last": "2014-04-16T16:00:00", "Count": 10 }
My idea is to to do a map/reduce view and query setting group to true.
This is what I have so far tried. I get the exact count, but not the correct dates.
map
function (doc, meta) {
if(doc.type =="doc")
emit(doc.key, doc.date);
}
reduce
function(key, values, rereduce) {
var result = {
Last: 0,
Count: 0
};
if (rereduce) {
for (var i = 0; i < values.length; i++) {
result.Count += values[i].Count;
result.Last = values[i].Last;
}
} else {
result.Count = values.length;
result.Last = values[0]
}
return result;
}
You're not comparing dates... Couchbase sorts values by key. In your situation it will not sort it by date, so you should do it manually in your reduce function. Probably it will look like:
result.Last = values[i].Last > result.Last ? values[i].Last : result.Last;
and in reduce function it also can be an array, so I don't think that your reduce function always be correct.
Here is an example of my reduce function that filter documents and leave just one that have the newest date. May be it will be helpful or you can try to use it (seems it looks like reduce function that you want, you just need to add count somewhere).
function(k,v,r){
if (r){
if (v.length > 1){
var m = v[0].Date;
var mid = 0;
for (var i=1;i<v.length;i++){
if (v[i].Date > m){
m = v[i].Date;
mid = i;
}
}
return v[mid];
}
else {
return v[0] || v;
}
}
if (v.length > 1){
var m = v[0].Date;
var mid = 0;
for (var i=1;i<v.length;i++){
if (v[i].Date > m){
m = v[i].Date;
mid = i;
}
}
return v[mid];
}
else {
return v[0] || v;
}
}
UPD: Here is an example of what that reduce do:
Input date (values) for that function will look like (I've used just numbers instead of text date to make it shorter):
[{Date:1},{Date:3},{Date:8},{Date:2},{Date:4},{Date:7},{Date:5}]
On the first step rereduce will be false, so we need to find the biggest date in array, and it will return
Object {Date: 8}.
Note, that this function can be called one time, but it can be called on several servers in cluster or on several branches of b-tree inside one couchbase instance.
Then on next step (if there were several machines in cluster or "branches") rereduce will be called and rereduce var will be set to true
Incoming data will be:
[{Date:8},{Date:10},{Date:3}], where {Date:8} came from reduce from one server(or branch), and other dates came from another server(or branch).
So we need to do exactly the same on that new values to find the biggest one.
Answering your question from comments: I don't remember why I used same code for reduce and rereduce, because it was long time ago (when couchbase 2.0 was in dev preview). May be couchbase had some bugs or I just tried to understand how rereduce works. But I remember that without that if (r) {..} it not worked at that time.
You can try to place return v; code in different parts of my or your reduce function to see what it returns on each reduce phase. It's better to try once by yourself to understand what actually happens there.
I forget to mention that I have many documents for the same key. In fact for each key I can have many documents( message here):
{
"date": "2014-04-16T17:13:00",
"key": "de5cefc56ff51c33351459b88d42ca9f828445c0",
"message": "message1",
}
{
"date": "2014-04-16T15:22:00",
"key": "de5cefc56ff51c33351459b88d42ca9f828445c0",
"message": "message2",
}
Another way to deal with the problem is to do it in the map function:
function (doc, meta) {
var count = 0;
var last =''
if(doc.type =="doc"){
for (k in doc.message){
count += 1;
last = doc.date> last?doc.date:last;
}
emit(doc.key,{'Count':count,'Last': last});
}
}
I found this simpler and it do the job in my case.

s:List display the items in reverse order

Is there a way to get a s:List to display it's items in reverse order? Not having to make a copy of the dataProvider would be ideal. Thanks.
You can set a Sort on your dataProvider (assuming it implements ICollectionView, like an ArrayCollection for example) and call the Sort.reverse() method. Hope that helps.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/collections/Sort.html
The s:List control does not have the option to show items in reverse order.
All is controlled by manipulating the dataProvider or the "source" of the dataProvide.
Here is how you could achieve this
public function showReverseList(data:Array):void
{
var reverseList:Array;
var i,count = data.length;
for(i = count-1 ; i >= 0 ; i--)
{
// add items in reverse order
reverseList.push(data[i]);
}
myListControl.dataProvider = reverseList;
}
This does the job for me
if (list && list.dataProvider)
{
list.dataProvider = new ArrayCollection((list.dataProvider as ArrayCollection).toArray().reverse());
}