How to count category value of array of List - list

let's say I have a list like the example below
<Categories>myList = [
Categories(
nameCategory: 'Book',
amount: '20'
),
Categories(
nameCategory: 'Book',
amount: '40'
),
Categories(
nameCategory: 'Food',
amount: '20'
),
Categories(
nameCategory: 'Food',
amount: '15'
),
];
How I can combine the duplicate values of that list and count the value of the list based on name ??
I can combine the list and the count value of the list but that only works just in a general list like sum total
what I want to do is make a new List but only combine several parts that share the same property like the same category or same class like that
this is an example what I want to achieve
<Categories> anotherList= [
Categories(
nameCategory: 'Book',
amount: '60'
),
Categories(
nameCategory: 'Food',
amount: '35'
),
];

I would replace your List<Categories> with a Map<String, Categories>. Then you can easily look up the Categories object given its name and mutate the existing Categories object. For example, something like:
var mergedCategories = <String, Categories>{};
for (var categories in myList) {
var name = categories.nameCategory;
var amount = categories.amount;
(mergedCategories[name] ??= Categories(nameCategory: name, amount: 0))
.amount += amount;
}

You're essentially trying to get an aggregate value from a list, which is what List.fold is meant to help with.
Here's an example of how you might use it:
class Category {
final String name;
int amount;
Category({required this.name, required this.amount});
String toString() => "Category(name: $name, amount: $amount)";
}
void main() {
final categories = [
Category(
name: 'Book',
amount: 20
),
Category(
name: 'Book',
amount: 40
),
Category(
name: 'Food',
amount: 20
),
Category(
name: 'Food',
amount: 15
),
];
/**
* Here is where the aggregation is done
*/
final List<Category> aggregated = categories.fold([], (list, item) {
try {
// Check whether the category is already in the aggregate
final existingCategory = list.firstWhere((c) => c.name == item.name);
// Category is already in the list, so just add the amount of the current item.
existingCategory.amount += item.amount;
return list;
} catch (_) {
// The category has not yet been added - so add it here
list.add(item);
return list;
}
});
print(aggregated);
}
I've changed your category class a bit for simplicity, but the principle should be the same. You can read more about the fold function here: https://api.dart.dev/stable/2.13.4/dart-core/Iterable/fold.html

A pretty straightforward method is by using the groupBy function provided by the collection.dart package.
import 'package:collection/collection.dart';
groupBy<Categories, String>(list, (c) => c.nameCategory).values.map(
(list) => list.reduce(
(a, b) => new Categories(a.nameCategory, a.amount + b.amount)
)
);

Related

Flutter Filter List base on Month

How I can categorise list based on Month
let say I have example list like below :
Record(
id: '01',
nameFood: 'ravioli',
date : 2021/may/14,
price: 20
),
Record(
id: '02',
nameFood: 'cheese garlic',
date : 2021/june/02,
price: 30,
),
Record(
id: '03',
nameFood: 'steak',
date : 2021/march/21
price 25,
),
I want to Categorize it to like this
June(
nameFood: steak,
total price: 240,
),
and etc
the problem is I dnt know how to filter each List(month) because each month have different length of days like 30,31 and 28
If you store your dates as a DateTime, you can try using the month number. I'm going on a limb here, assuming you have a List of objects of type Record, where Record is.
class Record {
Record(
this.id,
this.price,
this.date,
this.nameFood,
);
final String id;
final double price;
final DateTime date;
final String nameFood;
}
You can loop through your list and do whatever it is you want to do with it, like so.
for (final record in _listOfRecords) {
final _monthOfRecord = record.date.month; // Gives the month number. January = 1, April = 4, etc.
// Do other stuff, based on the current monthNumber
switch (_monthOfRecord) {
case 1:
// Do something
break;
....
default:
break;
}
}

how to get value of item in array of list and make them independent list

I have list like example below, I want to get value of nameCategory and make them to List
List<Categories> iconCategory= [
Categories(
iconPath: 'assets/images/icons/IncomeIcon/001-salary.svg',
nameCategory: 'Salary',
),
Categories(
iconPath: 'assets/images/icons/IncomeIcon/002-interest.svg',
nameCategory: 'Interest',
),
Categories(
iconPath: 'assets/images/icons/IncomeIcon/003-award.svg',
nameCategory: 'Award',
)];
to list like example below but the data is from array list above
how I can do that
List<String> myCategory = ['Salary','Interest','Award'];
You can simply use the map method to achieve this:
List<String> myCategory = mycategories.map((e) => e.nameCategory).toList();
print(myCategory); // Prints [Salary, Interest, Award]
this will give you what you need
List<Categories> s1 = [];
List<String> ss = [];
result!.map((e) {
ss.add(e.nameCategory);
});

how to create a list <> in flutter from Firestore?

I am new to flutter.
How can I retrieve data from Firestore and form a new profile with every child in my collection? Second question is how can I use this list in another dart file? thank you
Thank you.
final List<Profile> demoProfiles = [
Profile (
photos: [
"https://",
],
name: "abc",
),
Profile (
photos: [
"https://",
],
name: "abc",
)
];
Assuming you have a firestore strucuture like this:
Profile
photos: []
name: ""
age: ""
distance: ""
education: ""
You can fetch data and build it into your object with this code snippet:
fetchData() async{
final db = await Firestore.instance;
List<Profile> demoProfiles = []
db.collection("Profile").get().then(function(snapshot){
snapshot.forEach((document) {
demoProfiles.add(Profile(
photos: document.data.photos,
name: document.data.name,
age: document.data.age,
distance: document.data.distance,
education: document.data.education
))
})
})
}
Edit:
1) Remove the mockedup list of profiles from your profiles class, it should not be there
2) Edit your mainController to the following:
class _MainControllerState extends State<MainController> {
List<Profile> demoProfiles = [];
demoProfiles = fetchData();
Final MatchEngine match Engine = MatchEngine (
matches:demoProfiles.map((Profile profile) => Match(profile: profile)).toList();
);
fetchData() async{
final db = await Firestore.instance;
List<Profile> list = [];
db.collection("Profile").get().then(function(snapshot){
snapshot.forEach((document) {
list.add(Profile(
photos: document.data.photos,
name: document.data.name,
age: document.data.age,
distance: document.data.distance,
education: document.data.education
))
})
});
return list;
}
}

Search for Substring in several fields with MongoDB and Mongoose

I am so sorry, but after one day researching and trying all different combinations and npm packages, I am still not sure how to deal with the following task.
Setup:
MongoDB 2.6
Node.JS with Mongoose 4
I have a schema like so:
var trackingSchema = mongoose.Schema({
tracking_number: String,
zip_code: String,
courier: String,
user_id: Number,
created: { type: Date, default: Date.now },
international_shipment: { type: Boolean, default: false },
delivery_info: {
recipient: String,
street: String,
city: String
}
});
Now user gives me a search string, a rather an array of strings, which will be substrings of what I want to search:
var search = ['15323', 'julian', 'administ'];
Now I want to find those documents, where any of the fields tracking_number, zip_code, or these fields in delivery_info contain my search elements.
How should I do that? I get that there are indexes, but I probably need a compound index, or maybe a text index? And for search, I then can use RegEx, or the $text $search syntax?
The problem is that I have several strings to look for (my search), and several fields to look in. And due to one of those aspects, every approach failed for me at some point.
Your use case is a good fit for text search.
Define a text index on your schema over the searchable fields:
trackingSchema.index({
tracking_number: 'text',
zip_code: 'text',
'delivery_info.recipient': 'text',
'delivery_info.street': 'text',
'delivery_info.city': 'text'
}, {name: 'search'});
Join your search terms into a single string and execute the search using the $text query operator:
var search = ['15232', 'julian'];
Test.find({$text: {$search: search.join(' ')}}, function(err, docs) {...});
Even though this passes all your search values as a single string, this still performs a logical OR search of the values.
Why just dont try
var trackingSchema = mongoose.Schema({
tracking_number: String,
zip_code: String,
courier: String,
user_id: Number,
created: { type: Date, default: Date.now },
international_shipment: { type: Boolean, default: false },
delivery_info: {
recipient: String,
street: String,
city: String
}
});
var Tracking = mongoose.model('Tracking', trackingSchema );
var search = [ "word1", "word2", ...]
var results = []
for(var i=0; i<search.length; i++){
Tracking.find({$or : [
{ tracking_number : search[i]},
{zip_code: search[i]},
{courier: search[i]},
{delivery_info.recipient: search[i]},
{delivery_info.street: search[i]},
{delivery_info.city: search[i]}]
}).map(function(tracking){
//it will push every unique result to variable results
if(results.indexOf(tracking)<0) results.push(tracking);
});
Okay, I came up with this.
My schema now has an extra field search with an array of all my searchable fields:
var trackingSchema = mongoose.Schema({
...
search: [String]
});
With a pre-save hook, I populate this field:
trackingSchema.pre('save', function(next) {
this.search = [ this.tracking_number ];
var searchIfAvailable = [
this.zip_code,
this.delivery_info.recipient,
this.delivery_info.street,
this.delivery_info.city
];
for (var i = 0; i < searchIfAvailable.length; i++) {
if (!validator.isNull(searchIfAvailable[i])) {
this.search.push(searchIfAvailable[i].toLowerCase());
}
}
next();
});
In the hope of improving performance, I also index that field (also the user_id as I limit search results by that):
trackingSchema.index({ search: 1 });
trackingSchema.index({ user_id: 1 });
Now, when searching I first list all substrings I want to look for in an array:
var andArray = [];
var searchTerms = searchRequest.split(" ");
searchTerms.forEach(function(searchTerm) {
andArray.push({
search: { $regex: searchTerm, $options: 'i'
}
});
});
I use this array in my find() and chain it with an $and:
Tracking.
find({ $and: andArray }).
where('user_id').equals(userId).
limit(pageSize).
skip(pageSize * page).
exec(function(err, docs) {
// hooray!
});
This works.

Order list of objects by custom order initialized in other list

i have list a of objects which type is Person :
class Person{
int id
String name
String bestColor
}
def persons = [ new Person(1,'Abdennour','white'),
new Person(2,'Ali','red'),
new Person(3,'Hsen','white'),
new Person(4,'Aicha','green') ]
and i have a list of color:
def colors=['green','white','red']
i want to order persons list according to 3rd field(bestColor) . However, I do not want alphabetical order of colors , but rather I want the same order as colors list.
that it means , the expected result is :
def persons=[new Person(4,'Aicha','green')
,new Person(1,'Abdennour','white')
,new Person(3,'Hsen','white')
,new Person(2,'Ali','red')]
So given:
#groovy.transform.Canonical
class Person{
int id
String name
String bestColor
}
def persons = [ new Person( 1, 'Abdennour', 'white' ),
new Person( 2, 'Ali', 'red' ),
new Person( 3, 'Hsen', 'white' ),
new Person( 4, 'Aicha', 'green' ) ]
def colors = [ 'green','white','red' ]
You can just do:
// Sort (mutating the persons list)
persons.sort { colors.indexOf( it.bestColor ) }
// check it's as expected
assert persons.id == [ 4, 1, 3, 2 ]