I have a list map like below :
[
data{text: hello, date: 2020-09-11}, data{text: hi, date: 2020-09-12},
data{text: why, date: 2020-09-11}, data{text: how, date: 2020-09-10},
data{text: when, date: 2020-09-11}, data{text:flutter, date: 2020-09-12}
]
and what I want to get is this :
{
2020-09-10 : [how],
2020-09-11 : [hello, why, when],
2020-09-12 : [hi, flutter]
}
I'm a bit confusing between list<map> and list , I have no idea how to solve this.
I already know remove duplicate things with method toSet().toList().
Is there any method related with this? Thanks in advance.
-------------------- After following answer -----------------------
date => createTime, text => repeat
loadRepeat() async {
DBHelperRepeat sd = DBHelperRepeat();
var list = await sd.repeats();
List newList = [];
if (list[0].createTime == list[1].createTime) {
newList.add({
'date': list[0].createTime,
'repeat': list[0].repeat + ',' + list[1].createTime
});
} else {
newList.add({'date': list[0].createTime, 'repeat': list[0].repeat});
newList.add({'date': list[1].createTime, 'repeat': list[1].repeat});
}
for (int i = 2; i < list.length; i++) {
if (list[i].createTime == newList.last.createTime) {
newList.last.repeat += ',' + list[i].repeat;
} else {
newList.add(list[i]);
}
}
print(newList);
}
and here's my sqlite db code
repeat.dart
class Repeat {
final String repeat;
final String createTime;
final int year;
final int month;
final int date;
Repeat({this.repeat, this.createTime, this.year, this.month, this.date});
Map<String, dynamic> toMap() {
return {
'repeat': repeat,
'createTime': createTime,
'year': year,
'month': month,
'date': date
};
}
#override
String toString() {
return '{repeat: $repeat, createTime: $createTime, year: $year, month: $month, date: $date}';
}
}
db_repeat.dart
class DBHelperRepeat {
var _db;
Future<Database> get database async {
if (_db != null) return _db;
_db = openDatabase(
join(await getDatabasesPath(), 'repeats.db'),
onCreate: (db, version) {
return db.execute(
"CREATE TABLE repeats(repeat TEXT, createTime TEXT, year INT, month INT, date INT)",
);
},
version: 1,
);
return _db;
}
Future<void> insertRepeat(Repeat repeat) async {
final db = await database;
await db.insert('repeats', repeat.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace);
}
Future<List<Repeat>> repeats() async {
final db = await database;
final List<Map<String, dynamic>> maps = await db.query('repeats');
return List.generate(maps.length, (i) {
return Repeat(
repeat: maps[i]['repeat'],
createTime: maps[i]['createTime'],
year: maps[i]['year'],
month: maps[i]['month'],
date: maps[i]['date']);
});
}
example data list:
[{repeat: repeat1, createTime: 2020-09-13, year: 2020, month: 9, date: 13}]
Maybe this can help you:
DBHelperRepeat sd = DBHelperRepeat();
List<Repeat> list = await sd.repeats();
list.sort((a,b)=> a.createTime.compareTo(b.createTime));
List<Repeat> newList = [];
if(list.length == 0){
return newList;
} else if(list.length == 1){
newList.addAll(list);
return newList;
}
if (list[0].createTime == list[1].createTime) {
newList.add(
Repeat(
createTime: list[0].createTime,
repeat: list[0].repeat+', '+list[1].repeat,
date: list[0].date,
month: list[0].month,
year: list[0].year
)
);
} else {
newList.add(list[0]);
newList.add(list[1]);
}
if(list.length < 3){
return newList;
}
for (int i = 2; i < list.length; i++) {
if (list[i].createTime == newList.last.createTime) {
Repeat last = newList.last;
Repeat repeat = Repeat(
createTime: last.createTime,
repeat: last.repeat+', ' + list[i].repeat,
date: last.date,
month: last.month,
year: last.year
);
newList.removeLast();
newList.add(repeat);
} else {
newList.add(list[i]);
}
}
newList.forEach((element) {
print(element.createTime);
print(element.repeat);
});
Related
Getting a getter length called on null error when I call the getCartQuantity() method. Something about the cart being null. I do not know what the problem is.
This is the actual ERROR MESSAGE!
NoSuchMethodError: The getter 'length' was called on null.
Receiver: null
tried calling: length
import 'package:butcherbox/models/productsModel.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class StoreLogic extends ChangeNotifier {
List<ProductsModel> _products;
List<ProductsModel> _cart;
ProductsModel _activeProduct = null;
StoreLogic() {
_products = [
ProductsModel(
id: 001,
imageText: 'images/biggiecombo.jpg',
name: 'ButcherBox Mini Combo Pack',
category: 'Beef and Chicken',
price: 500,
quantity: 0,
),
ProductsModel(
id: 002,
imageText: 'images/thecombopack.jpg',
name: 'ButcherBox Biggie Combo',
category: 'Beef and Chicken',
price: 950,
quantity: 0,
),
ProductsModel(
id: 003,
imageText: 'images/regular1kg.jpg',
name: 'ButcherBox Regular 1kg',
category: 'Beef',
price: 1800,
quantity: 0,
),
];
notifyListeners();
}
List<ProductsModel> get products => _products;
List<ProductsModel> get cart => _cart;
ProductsModel get activeProduct => _activeProduct;
setActiveProduct(ProductsModel p) {
_activeProduct = p;
}
addOneItemToCart(ProductsModel p) {
ProductsModel found =
_cart.firstWhere((a) => a.id == p.id, orElse: () => null);
if (found != null) {
found.quantity += 1;
} else {
_cart.add(p);
}
notifyListeners();
}
getCartQuantity() {
int totalItems = 0;
for (int i = 0; i < cart.length; i++) {
totalItems += cart[i].quantity;
}
return totalItems;
}
}
The cart.length returns the error
Check if your cart is null before performing an operation on it.
getCartQuantity() {
int totalItems = 0;
if(cart == null) return totalItems; //add this line.
for (int i = 0; i < cart.length; i++) {
totalItems += cart[i].quantity;
}
return totalItems;
}
But in general, it appears you are not using null-safety, which I strongly advise you to do.
I would like to use a where clause in my Firestore query, with a list in parameter.
I used a for loop to do this but when I want to add all my values in a variable, I have some problems with the add function (variable type problem).
I understand the problem but I don't what is the way I have to take to do this in another way ...
Can anyone help me?
Best regards :) ###It's my first question on stack! :D ###
in my main class:
var games = [
"uno",
"poker",
];
return StreamProvider<List<AppUserData>>.value(
initialData: [],
value: DatabaseService().users4(games),
child: Scaffold(....
in my database class
List<AppUserData> _list = [];
void addToList(AppUserData value) {
_list.add(value);
}
Stream<List<AppUserData>> users4 (List games) {
print(games);
var b;
var len = games.length;
for (var i = 0; i < len + 1; i++) {
b = FirebaseFirestore.instance.collection("users")
.where("games", isEqualTo: games[i]).snapshots().map(
_userListFromSnapshot);
print("$b");
addToList(b);
}
return b;
}
List<AppUserData> _userListFromSnapshot(
QuerySnapshot<Map<String, dynamic>> snapshot) {
return snapshot.docs.map((doc) {
return _userFromSnapshot(doc);
}).toList();
}
AppUserData _userFromSnapshot(DocumentSnapshot<Map<String, dynamic>> snapshot) {
var data = snapshot.data();
if (data == null) throw Exception("user not found");
return AppUserData(
uid: uid,
name: snapshot.data()['name'],
distance: snapshot.data()['distance'],
games: snapshot.data()['games'],
id: snapshot.data()['id'],
);
}
I think you're looking for whereIn
Try this:
Stream<List<AppUserData>> users4(List games) async* {
yield* FirebaseFirestore.instance
.collection("users")
.where("games", whereIn: games)
.snapshots()
.map((e) {
List<AppUserData> l =
e.docs.map((e) => _userFromMap(Map.from(e.data()))).toList();
return l;
});
}
AppUserData _userFromMap(Map<String, dynamic> map) {
if (map == null) throw Exception("user not found");
return AppUserData(
uid: uid,
name: map['name'],
distance: map['distance'],
games: map['games'],
id: map['id'],
);
}
I have a futurebuilder that builds the UI based on a List, it does the job, however I get duplicates due to the UI being built again and again whenever I navigate. My question is, is there a innate method in Dart that can remove duplicates from a list? I've tried this StackOverflow question however it doesn't work.
Here is my custom model:
class HomeList {
Widget navigateScreen;
String imagePath;
PatientInfo patientInfo;
HomeList({
this.navigateScreen,
this.imagePath = '',
this.patientInfo,
});
static List<HomeList> homeList = [];
}
Here is my function for the futureBuilder i'm getting the data from my cloud_firestore:
_getPatients() async {
if (didLoadpatients == 0) {
print('this is didloadpatients at start of func $didLoadpatients');
var document = await db
.collection('users')
.document(mUser.uid)
.collection('patients');
document.getDocuments().then((QuerySnapshot query) async {
query.documents.forEach((f) {
uids.add(f.data['uID']);
});
didLoadpatients++;
print('this is didloadpatients at end of func $didLoadpatients');
for (var i = 0; i < uids.length; i++) {
var userDocuments = await db.collection('users').document(uids[i]);
userDocuments.get().then((DocumentSnapshot doc) {
print(doc.data);
homeList.add(HomeList(
imagePath: 'assets/fitness_app/fitness_app.png',
patientInfo: new PatientInfo.fromFbase(doc.data)));
});
print(homeList);
}
});
} else
print('I am leaving the get patient function');
}
Future<bool> getData() async {
_getCurrentUser();
await Future.delayed(const Duration(milliseconds: 1500), () async {
_getPatients();
});
return true;
}
Any help would be appreciated thank you!
To remove duplicates you can use Set Data Structure instead of List.
Just use Set instead of List to get unique values only.
Before Adding you can Remove Element from model this will Work
dummymodel.removeWhere((m) => m.id == id);
dummymodel.add(dummymodel.fromJson(data));
To Remove Duplicates from Data Model simply use Set (Data structure),
Original List with Duplicate Entries:
List<MyDataModel> mList = [MyDataModel(1), MyDataModel(2), MyDataModel(1), MyDataModel(3)];
New List that removes duplicate Entries from your List<MyDataModel>:
List<MyDataModel> mNewList = list.toSet().toList();
Output:
The result will be like
MyDataModel(1), MyDataModel(2), MyDataModel(3)
To remove the duplicate elements from custom object list, you need to override == and hashcode methods in your POJO class and then add the items in Set and again convert set to list to remove duplicate objects. Below is the working code:-
class TrackPointList {
double latitude;
double longitude;
String eventName;
Time timeZone;
TrackPointList({
this.latitude,
this.longitude,
this.eventName,
this.timeZone,
});
#override
bool operator==(other) {
// Dart ensures that operator== isn't called with null
// if(other == null) {
// return false;
// }
if(other is! TrackPointList) {
return false;
}
// ignore: test_types_in_equals
return eventName == (other as TrackPointList).eventName;
}
int _hashCode;
#override
int get hashCode {
if(_hashCode == null) {
_hashCode = eventName.hashCode;
}
return _hashCode;
}
factory TrackPointList.fromJson(Map<String, dynamic> json) => TrackPointList(
latitude: json["latitude"].toDouble(),
longitude: json["longitude"].toDouble(),
eventName: json["eventName"],
timeZone: timeValues.map[json["timeZone"]],
);
Map<String, dynamic> toJson() => {
"latitude": latitude,
"longitude": longitude,
"eventName": eventName,
"timeZone": timeValues.reverse[timeZone],
};
}
Above is the POJO class. Now below is the method which helps you to filter the objects according to the eventName data member.
List<TrackPointList> getFilteredList(List<TrackPointList> list){
final existing = Set<TrackPointList>();
final unique = list
.where((trackingPoint) => existing.add(trackingPoint))
.toList();
return unique;
}
This will work definitely.
Please +1 if it helps you.
I've come up with quite a brute force solution. Instead of
_getPatients() async {
if (didLoadpatients == 0) {
print('this is didloadpatients at start of func $didLoadpatients');
var document = await db
.collection('users')
.document(mUser.uid)
.collection('patients');
document.getDocuments().then((QuerySnapshot query) async {
query.documents.forEach((f) {
uids.add(f.data['uID']);
});
didLoadpatients++;
print('this is didloadpatients at end of func $didLoadpatients');
for (var i = 0; i < uids.length; i++) {
var userDocuments = await db.collection('users').document(uids[i]);
userDocuments.get().then((DocumentSnapshot doc) {
print(doc.data);
homeList.add(HomeList(
imagePath: 'assets/fitness_app/fitness_app.png',
patientInfo: new PatientInfo.fromFbase(doc.data)));
});
print(homeList);
}
});
} else
print('I am leaving the get patient function');
}
I've done what #Jay Mungara says and clear my Set everytime my UI rebuilds:
_getPatients() async {
homeList.clear();
if (didLoadpatients == 0) {
print('this is didloadpatients at start of func $didLoadpatients');
var document = await db
.collection('users')
.document(mUser.uid)
.collection('patients');
document.getDocuments().then((QuerySnapshot query) async {
query.documents.forEach((f) {
uids.add(f.data['uID']);
});
didLoadpatients++;
print('this is didloadpatients at end of func $didLoadpatients');
for (var i = 0; i < uids.length; i++) {
var userDocuments = await db.collection('users').document(uids[i]);
userDocuments.get().then((DocumentSnapshot doc) {
print(doc.data);
homeList.add(HomeList(
imagePath: 'assets/fitness_app/fitness_app.png',
patientInfo: new PatientInfo.fromFbase(doc.data)));
});
print(homeList);
}
});
} else
print('I am leaving the get patient function');
}
Thank you for all your answers!
this is a small examples to remove duplicate element
removeDuplicate() {
List<dynamic> demoList = [
{"userId": 1, "id": 1, "name": "thappu1"},
{"userId": 2, "id": 2, "name": "appu"},
{"userId": 1, "id": 1, "name": "thappu1"},
{"userId": 2, "id": 2, "name": "appu"},
{"userId": 2, "id": 2, "name": "appu"},
{"userId": 2, "id": 2, "name": "appu"},
{"userId": 2, "id": 2, "name": "appu"},
];
var toRemove = {};
demoList.forEach((e) {
toRemove.putIfAbsent("$e", () => e);
});
print(toRemove.keys.toList());
}
output is
[{userId: 1, id: 1, name: thappu1}, {userId: 2, id: 2, name: appu}]
<Team Side="Home" TeamRef="ref123">
<Goal PlayerRef="p1111" Time="10" >
<Assist PlayerRef="p9999">p9999</Assist>
</Goal>
<Goal PlayerRef="p4444" Time="11" >
<Assist PlayerRef="p9999">p9999</Assist>
</Goal>
<Goal PlayerRef="p7777 Time="13" >
<Assist PlayerRef="p9999">p9999</Assist>
</Goal>
<Goal PlayerRef="p7777 Time="17" >
<Assist PlayerRef="p9999">p9999</Assist>
</Goal>
</Team>
public void GetScorer(string side, string OCompetition, string OSeason, string OGameId)
{
try
{
var xDoc = XDocument.Load(test);
var query = from q in xDoc.Descendants("Team")
where (string)q.Attribute("Side") == side
from d in q.Elements("Goal")
select new
{
TeamRef = q.Attribute("TeamRef").Value,
PlayerRef = d.Attribute("PlayerRef").Value,
Time = d.Attribute("Time").Value
};
var count = 0;
foreach (var qq in query)
{
if (side == "Home")
{
if (HomeSlateScorerList[count].PlayerRef != qq.PlayerRef)
{
HomeSlateScorerList.Add(new Scorer() { PlayerRef = qq.PlayerRef, Time = qq.Time, LastName = GetPlayerNameSlate(qq.PlayerRef, OSeason, OCompetition, OGameId) });
}
else
{
HomeSlateScorerList[count].Time = HomeSlateScorerList[count].Time + "' ";
}
}
if (side == "Away")
{
AwaySlateScorerList.Add(new Scorer() { PlayerRef = qq.PlayerRef, Time = qq.Time, LastName = GetPlayerNameSlate(qq.PlayerRef, OCompetition, OSeason, OGameId) });
}
count++;
}
}
catch (Exception)
{
// ignored
}
}
I would like to edit a player in a list of players
HomeSlateScorerList = new List<Scorer>();
AwaySlateScorerList = new List<Scorer>();
what I would like to achieve is for e.g. there are two players with the ref of "p7777" so in the list of object I would like to have one player with the playerref of "p7777" so if the player exist the format will be
playerref = "p7777"
Time = 13' 17'
or if one player its
Time = 13'
or if another goal is added to the xml its
Time = 13' 17' 25'
HomeSlateScorerList = HomeSlateScorerList
.GroupBy(s => s.PlayerRef)
.Select(g => new Scorer { PlayerRef = g.Key, Time = string.Join(", ", g.Select(v => v.Time)) })
.ToList();
Thanks to: #SergeyS SergeyS
I am soooo close here. I'm hoping a guru can help me with this last piece. I'm populating a jQuery DatePicker calendar with XML from an RSS feed. Upon clicking a highlighted date where there's an event, I'm creating a URL with a query string so I can display all the event for the clicked day. Everything is working... until I change the month by clicking previous or next month. My script will return the correct day, but is only returning the current month. For example, I navigate to May and click the 5th, my URL will be events.htm?month=june&day=5. Any ideas on why it will not return my selected month? Here's my code:
var data = $.ajax({
url: "news.xml",
type: "GET",
dataType: "xml",
async:false,
success: function(xml){
return xml;
}
} ).responseText;
$(document).ready(function() {
var events = getSelectedDates();
$("div.datepicker").datepicker({
beforeShowDay: function(date) {
var result = [true, '', null];
var matching = $.grep(events, function(event) {
return event.published.getDate() === date.getDate() && event.published.getMonth() === date.getMonth() && event.published.getFullYear() === date.getFullYear();
});
if (matching.length) {
result = [true, 'highlight', null];
}
return result;
},
onSelect: function(dateText) {
var date, selectedDate = new Date(dateText),
i = 0,
event = null;
while (i < events.length && !event) {
date = events[i].published;
if (selectedDate.getFullYear() === date.getFullYear() &&
selectedDate.getMonth() === date.getMonth() &&
selectedDate.getDate() === date.getDate()) {
event = events[i];
}
i++;
}
if (event) {
var eMonNum = event.published.getMonth();
var d = new Date();
var eMonNum = new Array();
eMonNum[0] = "january";
eMonNum[1] = "february";
eMonNum[2] = "march";
eMonNum[3] = "april";
eMonNum[4] = "may";
eMonNum[5] = "june";
eMonNum[6] = "july";
eMonNum[7] = "august";
eMonNum[8] = "september";
eMonNum[9] = "october";
eMonNum[10] = "november";
eMonNum[11] = "december";
var eMon = eMonNum[d.getMonth()];
var eDay = event.published.getDate();
window.location = "events.htm?month="+eMon+"&day="+eDay;
}
}
});
});
function getSelectedDates() {
return $(data).find('entry').map(function() {
return {
title: $('title', this).text(),
published: new Date($('published', this).text())
};
}).get();
}
Found the problem, when you copied this list from a resource, you forgot to replace the variables.
CHANGE (at the end of month list)
var eMon = eMonNum[d.getMonth()];
TO:
var eMon = eMonNum[event.published.getMonth()];
All I did was get rid of the bad variable and reassigned your month variable to the one you used for the day. You can also remove the declaration of the d variable, as you will not need it.
Best of luck!