Initializing Lists to Avoid Potential Errors - list

This function
List<int> _calculateTrips() {
List<int> trips = [];
trips = List.generate(
30,
(index) {
var counter = 0;
var aDay = DateTime.now().subtract(Duration(days: index));
for (var aWalk in walks) {
if ((aDay.month == aWalk.month) && (aDay.day == aWalk.day)) {
counter++;
}
}
trips.add(counter);
},
);
return trips;
}
creates the error The body might complete normally, causing null to be returned, but the return type is a potentially non-nullable type.Try adding either a return or a throw statement at the end. I'm struggling a bit to understand the message because (a) I thought I initialized the list at the beginning of the function and (b) I thought I had a return statement at the end.

The issue is with the function you pass to List.generate(). It expects a E Function(int), where E is the type of the element, for example:
final evenNumbers = List.generate(10, (index) {
return index * 2;
});
Your issue comes from trips.add(counter):
List<int> trips = [];
trips = List.generate(30, (index) {
final trip = calculateTrip(index);
trips.add(trip);
})
The inner function needs to be an int Function(int) (i.e. a function that takes an int, and returns an int), because your list is a List<int>.
However, your inner function never returns anything.
Simply replace trips.add(counter); with return counter; and it should solve this error. You may also want to refactor your function a little:
List<int> _calculateTrips() => List.generate(30, (index {
var counter = 0;
var aDay = DateTime.now().subtract(Duration(days: index));
for (var aWalk in walks) {
if ((aDay.month == aWalk.month) && (aDay.day == aWalk.day)) {
counter++;
}
}
return counter;
});

Related

How to remove a specific object from a list in dart/flutter?

I have a list called selected list of type dynamic and it holds a list of objects, each objects contains from a teacher ID & index.
I want to check if this list contains the same Id & index, if it does i want to remove this object from the list.
here is my code ....
void addTeacher(int teacherId, int index) {
if (this.selectedList.contains({ **/// the problem is here** })) {
this.selectedList.remove({teacherId, index});
this.myColor = Colors.grey;
print('removed teacher => ${teacherId.toString()}');
} else {
this.selectedList.add({teacherId, index});
this.myColor = AsasColors().blue;
print('added teacher => ${teacherId.toString()}');
}
notifyListeners();
print(selectedList);
}
how can i achive this ?
Contains and remove use the == operator which in this case will return false because unless you override it for a specific class it will compare by reference.
You can use indexWhere to find out if an item is in a list based on a compare function like that (if the function returns -1 the item is not on the list:
// Index different than -1 means the item is found somewhere in the list
final teacherIndex = this.selectedList.indexWhere((teacher) => teacher['teacherId'] == teacherId);
if (teacherIndex != -1) {
this.selectedList.removeAt(teacherIndex);
this.myColor = Colors.grey;
print('removed teacher => ${teacherId.toString()}');
} else {
...
}
I have implemented it and it worked fine
[The code]
[The output:]
This is the written code:
class Subject {
int? teacherID;
int? subjectID;
Subject(this.teacherID, this.subjectID);
#override
String toString() => "Subject {teacherID: $teacherID, subjectID: $subjectID";
//TODO: Change your needed criteria here..
#override
bool operator ==(Object other) =>
other is Subject &&
teacherID == other.teacherID &&
subjectID == other.subjectID;
}
void addSubject(List<Subject> list, Subject subject) {
if (list.contains(subject)) {
list.remove(subject);
} else {
list.add(subject);
}
}
void main() {
List<Subject> selectedList =
List.generate(10, (index) => Subject(index + 1, index + 1));
print("SelectedList = $selectedList");
addSubject(selectedList, Subject(11, 11));
addSubject(selectedList, Subject(11, 12));
addSubject(selectedList, Subject(12, 11));
addSubject(selectedList, Subject(12, 12));
print("SelectedList2 = $selectedList");
addSubject(selectedList, Subject(12, 12));
print("SelectedList3 = $selectedList");
}
Sincerely, accept the answer if it worked for you.

How to update a variable maintaining the length of a list in a cascade-like structure?

class CoinData {
var _controller = StreamController<Map<String,dynamic>>();
.....
Stream<Map<String,dynamic>> getAllCurrentRates() {
int numAssets = 0;
int counter = 0;
this.listAllAssets()
.then((list) {
if (list != null) {
numAssets = list.length;
List<Map<String, dynamic>>.from(list)
.where((map) => map["type_is_crypto"] == 1)
.take(3)
.map((e) => e["asset_id"].toString())
.forEach((bitCoin) {
this.getCurrentRate(bitCoin)
.then((rate) => _controller.sink.add(Map<String,dynamic>.from(rate)))
.whenComplete(() {
if (++counter >= numAssets) _controller.close();
});
});
}
});
return _controller.stream;
}
.....
}
The length of returned list is around 2500 and this value is assumed by numAssets, however as you see that list is modified later and therefore its length is less, then the evaluation (++counter >= numAssets) is incorrect. So, is it possible to fix that code maintaining its current structure?
.take(3) is temporal, it shall be removed later.

Scala function takes 2 hours with 2 million values

Would be grateful if any ideas to speed it up!
case class Pair(aa:String, bb:String)
case class OutputRow(bb:String, aa:String, bb_2:String, aa_2:String)
def startSearch(
_1_sorted: Array[Pair] ,
_2_hashmap: HashMap[String, String] ) : ArrayBuffer[OutputRow] = {
var outputTableListBuffer = ArrayBuffer[OutputRow]()
var searchComparisionFlag = false
var storeMain = Pair("0","0") //Initialize with Dummy data
var i = 0
def search(xxxx_1: Pair): Unit = {
if (searchComparisionFlag==true) {
var _2_exists = _2_hashmap.exists(_._1 == xxxx_1.aa)
if (_2_exists) {
val _2_xxxx = _2_hashmap(xxxx_1.aa)
outputTableListBuffer.append(OutputRow(storeMain.aa, storeMain.bb,_2_xxxx, xxxx_1.aa))
i = i + 1
if (i % 1000 == 0) println("In recursive search storeMain: ", storeMain)
var storePair = Pair(_2_xxxx,xxxx_1.aa)
search(storePair)
} else {
searchComparisionFlag = false
return
}
} else {
var _2_exists = _2_hashmap.exists(_._1 == xxxx_1.aa)
if (_2_exists) {
val _2_xxxx = _2_hashmap(xxxx_1.aa)
searchComparisionFlag = true
outputTableListBuffer.append(OutputRow(xxxx_1.aa, xxxx_1.bb,_2_xxxx, xxxx_1.aa))
var store = Pair(_2_xxxx,xxxx_1.aa)
search(store)
}
}
}
_1_sorted.foreach{ aa_1 =>
val store = Pair(aa_1.aa, aa_1.bb)
storeMain = store
search(store)
}
outputTableListBuffer
}
The above function takes 2 hours with 1 million values in _1_sorted and with a good 1 Million lookup in the hashmap.
Any ideas to speed this up?
This is a recursive logic function
The biggest problem is this:
_2_hashmap.exists(_._1 == xxxx_1.aa)
This is checking every single element of the hashmap on every call. Instead, use get:
_2_hashmap.get(xxxx_1.aa) match {
Some(_2_xxxx) => // Found
???
None => // Not found
???
}
Other code issues:
Don't use return
Pass flags down through recursive call rather than using global var
Use val wherever possible
Don't start variable names with _

Kth from the last element in a list using golang

I have the code to find the kth from the last element in a list in golang. I wrote a recursive function. When it reaches the end of the list, it will return the count as 1 and increments in further returns. When the count == k then return the node value. But I am getting 'nil pointer dereference' error. Could anyone help me in this?
package main
import (
"container/list"
"fmt"
)
var sMap map[int]bool
func main() {
l := list.New()
for i := 1; i < 100; i++ {
l.PushBack(i)
}
kFromLastElemRec := findKFromLastRecr(l.Front(), 3, WrapObj{0})
fmt.Println(kFromLastElemRec.Value.(int))
}
//Object to store the count
type WrapObj struct {
count int
}
//ERROR
//recursive function to find the kth from last element
func findKFromLastRecr(head *list.Element, k int, wrapper WrapObj) *list.Element {
if head == nil {
return nil
}
resNode := findKFromLastRecr(head.Next(), k, wrapper)
wrapper.count = (wrapper.count) + 1
if wrapper.count == k {
return head
}
return resNode
}
You need to pass a pointer to WrapObj to the findKFromLastRecr() function.
Similar to the languages in the C family, everything in Go is passed by value. That is, a function always gets a copy of the thing being passed, as if there were an assignment statement assigning the value to the parameter.
For instance, passing a WrapObj value to a function makes a copy of the WrapObj, but not the WrapObj it points to.
Therefore, without a pointer to WrapObj, each findKFromLastRecr() function gets a copy of WrapObj and the increase can not be shared by the outer findKFromLastRecr() functions.
It could be useful to check the pointers section from golang-book.
package main
import (
"container/list"
"fmt"
)
var sMap map[int]bool
func main() {
l := list.New()
for i := 1; i < 100; i++ {
l.PushBack(i)
}
kFromLastElemRec := findKFromLastRecr(l.Front(), 3, &WrapObj{0})
fmt.Println(kFromLastElemRec.Value.(int))
}
//Object to store the count
type WrapObj struct {
count int
}
//ERROR
//recursive function to find the kth from last element
func findKFromLastRecr(head *list.Element, k int, wrapper *WrapObj) *list.Element {
if head == nil {
return nil
}
resNode := findKFromLastRecr(head.Next(), k, wrapper)
wrapper.count = (wrapper.count) + 1
if wrapper.count == k {
return head
}
return resNode
}
Output
97

Fuzzy Matches on dijit.form.ComboBox / dijit.form.FilteringSelect Subclass

I am trying to extend dijit.form.FilteringSelect with the requirement that all instances of it should match input regardless of where the characters are in the inputted text, and should also ignore whitespace and punctuation (mainly periods and dashes).
For example if an option is "J.P. Morgan" I would want to be able to select that option after typing "JP" or "P Morgan".
Now I know that the part about matching anywhere in the string can be accomplished by passing in queryExpr: "*${0}*" when creating the instance.
What I haven't figured out is how to make it ignore whitespace, periods, and dashes. I have an example of where I'm at here - http://jsfiddle.net/mNYw2/2/. Any help would be appreciated.
the thing to master in this case is the store fetch querystrings.. It will call a function in the attached store to pull out any matching items, so if you have a value entered in the autofilling inputfield, it will eventually end up similar to this in the code:
var query = { this.searchAttr: this.get("value") }; // this is not entirely accurate
this._fetchHandle = this.store.query(query, options);
this._fetchHandle.then( showResultsFunction );
So, when you define select, override the _setStoreAttr to make changes in the store query api
dojo.declare('CustomFilteringSelect', [FilteringSelect], {
constructor: function() {
//???
},
_setStoreAttr: function(store) {
this.inherited(arguments); // allow for comboboxmixin to modify it
// above line eventually calls this._set("store", store);
// so now, 'this' has 'store' set allready
// override here
this.store.query = function(query, options) {
// note that some (Memory) stores has no 'fetch' wrapper
};
}
});
EDIT: override queryEngine function as opposed to query function
Take a look at the file SimpleQueryEngine.js under dojo/store/util. This is essentially what filters the received Array items on the given String query from the FilteringSelect. Ok, it goes like this:
var MyEngine = function(query, options) {
// create our matching query function
switch(typeof query){
default:
throw new Error("Can not query with a " + typeof query);
case "object": case "undefined":
var queryObject = query;
query = function(object){
for(var key in queryObject){
var required = queryObject[key];
if(required && required.test){
if(!required.test(object[key])){
return false;
}
}else if(required != object[key]){
return false;
}
}
return true;
};
break;
case "string":
/// HERE is most likely where you can play with the reqexp matcher.
// named query
if(!this[query]){
throw new Error("No filter function " + query + " was found in store");
}
query = this[query];
// fall through
case "function":
// fall through
}
function execute(array){
// execute the whole query, first we filter
var results = arrayUtil.filter(array, query);
// next we sort
if(options && options.sort){
results.sort(function(a, b){
for(var sort, i=0; sort = options.sort[i]; i++){
var aValue = a[sort.attribute];
var bValue = b[sort.attribute];
if (aValue != bValue) {
return !!sort.descending == aValue > bValue ? -1 : 1;
}
}
return 0;
});
}
// now we paginate
if(options && (options.start || options.count)){
var total = results.length;
results = results.slice(options.start || 0, (options.start || 0) + (options.count || Infinity));
results.total = total;
}
return results;
}
execute.matches = query;
return execute;
};
new Store( { queryEngine: MyEngine });
when execute.matches is set on bottom of this function, what happens is, that the string gets called on each item. Each item has a property - Select.searchAttr - which is tested by RegExp like so: new RegExp(query).test(item[searchAttr]); or maybe a bit simpler to understand; item[searchAttr].matches(query);
I have no testing environment, but locate the inline comment above and start using console.debug..
Example:
Stpre.data = [
{ id:'WS', name: 'Will F. Smith' },
{ id:'RD', name:'Robert O. Dinero' },
{ id:'CP', name:'Cle O. Patra' }
];
Select.searchAttr = "name";
Select.value = "Robert Din"; // keyup->autocomplete->query
Select.query will become Select.queryExp.replace("${0]", Select.value), in your simple queryExp case, 'Robert Din'.. This will get fuzzy and it would be up to you to fill in the regular expression, here's something to start with
query = query.substr(1,query.length-2); // '*' be gone
var words = query.split(" ");
var exp = "";
dojo.forEach(words, function(word, idx) {
// check if last word
var nextWord = words[idx+1] ? words[idx+1] : null;
// postfix 'match-all-but-first-letter-of-nextWord'
exp += word + (nextWord ? "[^" + nextWord[0] + "]*" : "");
});
// exp should now be "Robert[^D]*Din";
// put back '*'
query = '*' + exp + '*';