Flutter how to link arrays by ids - flutter

I have data like this
var sendlocal = [
{
"firstName": "tree",
"lastName": "tree",
"relativeEmail": "tree#gmail.com",
"relativeType": 0,
"subid": 1,
"subRelatives": [
{
"firstName": "julia2",
"lastName": "Michle",
"relativeEmail": "test#hotmail.com3",
"relativeType": 2,
"subid": 2,
"subRelatives": [
{
"firstName": "john",
"lastName": "bravo",
"relativeEmail": "johny#gmail.com",
"relativeType": 1,
"subRelatives": [],
"subid": 3,
},
{
"firstName": "simith",
"lastName": "bravo",
"relativeEmail": "johny#gmail.com",
"relativeType": 1,
"subRelatives": [],
"subid": 4,
},
],
},
{
"firstName": "julia3",
"lastName": "Michle",
"relativeEmail": "test3#hotmail.com",
"relativeType": 2,
"subRelatives": [],
"subid": 5,
},
],
},
];
And as per below answer(Thanks) I create a function like this
getIndexFromNestedList(List<dynamic> mapValue) {
if (mapValue != null) {
for (var relation in mapValue) {
print(relation['subid']);
print(relation['relativeEmail']);
if (relation['subRelatives'] != null) {
for (var subRelation in relation['subRelatives']) {
print({relation['subid'], subRelation['subid']});
// graph.addEdge(relation['subid'], subRelation['subid']); //like this
Future.delayed(Duration(milliseconds: 1), () {
getIndexFromNestedList(relation['subRelatives']);
});
}
}
}
}
}
and pass data like this
var check = getIndexFromNestedList(relatives);
And I getting responses like this
flutter: {1, 2}
flutter: {1, 3}
4flutter: {2, null}
What Expected is {2,3} {2,4} and so on if sub relative also have sub relative. But it's showing null don't know why when it's going to sub relatives.

You can use a nested for loop to get those values like the following and resend the loop to the method to get the nested values
getIndexFromNestedList(List<dynamic> mapValue) {
for (var relation in mapValue) {
if (relation['sub'] != null) {
for (var subRelation in relation['sub']) {
print({relation['id'], subRelation['id']});//you can add it directly to the map here.
graph.addEdge(relation['id'], subRelation['id']);//like this
Future.delayed(Duration(milliseconds:1), (){//future is added to finish the first loop then to enter into the inner loops.
getIndexFromNestedList(relation['sub']);
});
}
}
}
}
//OUTPUT
{1, 2}
{1, 6}
{2, 3}
{2, 5}
{2, 3}
{2, 5}
{3, 4}
{3, 4}
{3, 4}
{3, 4}
you can use this method to set the values into the graph
getIndexFromNestedList(reList);
EDIT
for the current structure you can check if the first value is not null before you access its children like the following
getIndexFromNestedList(List<dynamic> mapValue) {
if (mapValue != null) {
for (var relation in mapValue) {
print(relation['subid']);
print(relation['relativeEmail']);
if (relation['subRelatives'] != null) {
for (var subRelation in relation['subRelatives']) {
print({relation['subid'], subRelation['subid']});
// graph.addEdge(relation['subid'], subRelation['subid']); //like this
Future.delayed(Duration(milliseconds: 1), () {
getIndexFromNestedList(relation['subRelatives']);
});
}
}
}
}
}
Edit on 7AUG
In the question again you missed to check if its a null value and if length is greater than 0. also you are passing relatives to the method.. The list name wassendlocal
Here is the updated method with length check too
getIndexFromNestedList(List mapValue) {
if (mapValue != null) {
for (int i = 0; i < mapValue.length; i++) {
for (int j = 0; j < mapValue[i]['subRelatives'].length; j++) {
Map subList = mapValue[i]['subRelatives'][j];
print({mapValue[i]['subid'], subList['subid']});
if (subList['subRelatives'].length > 0) {
Future.delayed(Duration(milliseconds: 10), () {
getIndexFromNestedList(mapValue[i]['subRelatives']);
});
}
}
}
}
}
//Output
flutter: {1, 2}
flutter: {1, 5}
flutter: {2, 3}
flutter: {2, 4}
Tested this multiple times and removed all duplicates too.

I got your answer as per your requirement, maybe this helpful for you
void main(){
var check =getIndexFromList(sendlocal);
}
getIndexFromList(List sendlocal) {
if (sendlocal != null) {
for (var relation in sendlocal) {
print('subid:- ${relation['subid']}');
print('relativeEmail:- ${relation['relativeEmail']}');
if (relation['subRelatives'] != null && relation['subRelatives'].length > 0) {
for (var subRelation in relation['subRelatives']) {
//its your required response
print({relation['subid'], subRelation['subid']});
Future.delayed(Duration(milliseconds: 2), () {
getIndexFromList(relation['subRelatives']);
});
}
}
}
}
}
var sendlocal = [
{
"firstName": "tree",
"lastName": "tree",
"relativeEmail": "tree#gmail.com",
"relativeType": 0,
"subid": 1,
"subRelatives": [
{
"firstName": "julia2",
"lastName": "Michle",
"relativeEmail": "test#hotmail.com3",
"relativeType": 2,
"subid": 2,
"subRelatives": [
{
"firstName": "john",
"lastName": "bravo",
"relativeEmail": "johny#gmail.com",
"relativeType": 1,
"subRelatives": [],
"subid": 3,
},
{
"firstName": "simith",
"lastName": "bravo",
"relativeEmail": "johny#gmail.com",
"relativeType": 1,
"subRelatives": [],
"subid": 4,
},
],
},
{
"firstName": "julia3",
"lastName": "Michle",
"relativeEmail": "test3#hotmail.com",
"relativeType": 2,
"subRelatives": [],
"subid": 5,
},
],
},
];
The response is something like that,
subid:- 1
relativeEmail:- tree#gmail.com
{1, 2}
{1, 5}
subid:- 2
relativeEmail:- test#hotmail.com3
{2, 3}
{2, 4}
subid:- 5
relativeEmail:- test3#hotmail.com
subid:- 2
relativeEmail:- test#hotmail.com3
{2, 3}
{2, 4}
subid:- 5
.............
.............

Related

How to display a single Item from an array of objects - flutter

Hello I need help with a question that's a little tricky. I have an array of objects below. These objects are gotten as a results of a get http request I made to an endpoint. The endpoint requires some Ids and those Ids are also returned in the response objects which are: anchorOid, providerOid, and StateOid. So before this response a user will select an anchor, state and provider then it make request to the end point and return the users Stocks object which is the object below. So whatever the user selects before the http request, those are the IDs that would be returned in the response. So my challenge is after getting the response, before I loop through the whole objects and display them using datatable row and column, how can I display just the anchor, State, before iterating over the whole object just to show the user that this is the anchor and state you selected since the anchor and state are the same in all the objects hence the originate from the users selection. How can can do that please?
_getStocksByProviderIdByAnchorIdBySeasonId() async {
try {
_prefs = await SharedPreferences.getInstance();
var _stockService = StockService();
var result =
await _stockService.getStocksByProviderIdByAnchorIdBySeasonId(
_prefs.getInt('providerOid'),
widget.anchorOid,
widget.seasonOid,
widget.stateOid);
var stocks = await json.decode(result.body);
_stocks = <Stock>[];
stocks.forEach((stock) {
var _stock = Stock();
_stock.oid = stock['oid'];
_stock.date = DateTime.parse(stock['date']);
_stock.anchor = stock['anchor'];
_stock.state = stock['state'];
setState(() {
_stocks.add(_stock);
});
});
print("Stocks");
print(stocks);
setState(() {
data = stocks;
_isLoading = false;
});
} catch (e) {
setState(() {
_isLoading = false;
});
return e.toString();
}
}
I tried to do this:
stocks[0]['anchor]
but its only picking the first index so how do I make the index dynamic I don't know what to do.
[
{
"oid": 3,
"anchor": "MAIZE ASSOCIATION OF NIGERIA",
"anchorOid": 1,
"date": "2021-07-09T14:37:00.403",
"provider": "ERG Agro Solutions",
"providerOid": 1,
"season": "WET SEASON - 2020",
"seasonOid": 1,
"stateOid": 1,
"state": "Abia",
"stockItems": [],
"totalStockItems": 0
},
{
"oid": 4,
"anchor": "MAIZE ASSOCIATION OF NIGERIA",
"anchorOid": 1,
"date": "2021-08-09T14:39:00.403",
"provider": "ERG Agro Solutions",
"providerOid": 1,
"season": "WET SEASON - 2020",
"seasonOid": 1,
"stateOid": 1,
"state": "Abia",
"stockItems": [],
"totalStockItems": 0
}
]
You can try the first method on List like this,
void main() {
List data = [
{
"oid": 3,
"anchor": "MAIZE ASSOCIATION OF NIGERIA",
"anchorOid": 1,
"date": "2021-07-09T14:37:00.403",
"provider": "ERG Agro Solutions",
"providerOid": 1,
"season": "WET SEASON - 2020",
"seasonOid": 1,
"stateOid": 1,
"state": "Abia",
"stockItems": [],
"totalStockItems": 0
},
{
"oid": 4,
"anchor": "MAIZE ASSOCIATION OF NIGERIA",
"anchorOid": 1,
"date": "2021-08-09T14:39:00.403",
"provider": "ERG Agro Solutions",
"providerOid": 1,
"season": "WET SEASON - 2020",
"seasonOid": 1,
"stateOid": 1,
"state": "Abia",
"stockItems": [],
"totalStockItems": 0
}
];
print(data.first['anchor']);
}
It will always pick the first element of an array.

What is the cleanest way to get the average of each item list in Dart?

I have a List<Expenses> in dart. It looks like this:
[
{itemId: 1,
quantity: 10.0
},
{itemId: 2,
quantity: 14.0
},
{itemId: 2,
quantity: 25.0
},
{itemId: 3,
quantity: 3.0
}
...
];
I would like to get the average of each itemId to obtain a List like this:
[
{itemId: 1,
quantity: 10.0
},
{itemId: 2,
quantity: 19.5
},
{itemId: 3,
quantity: 3.0
}
...
];
What is the simplest way to do that?
I wouldn't say it is the simplest but it works:
void main() {
List data = [
{"itemId": 1, "quantity": 10.0},
{"itemId": 2, "quantity": 14.0},
{"itemId": 2, "quantity": 25.0},
{"itemId": 3, "quantity": 3.0}
];
List formattedList(List list) {
var obj = {};
for (var i = 0; i < list.length; i++) {
if (obj[list[i]["itemId"]] == null) {
obj[list[i]["itemId"]] = {"count": 1, "quantity": list[i]["quantity"]};
} else {
obj[list[i]["itemId"]]["count"] += 1;
obj[list[i]["itemId"]]["quantity"] += list[i]["quantity"];
}
}
List sol = [];
for (var key in obj.keys) {
sol.add({"itemId": key, "quantity": obj[key]["quantity"] / obj[key]["count"]});
}
return sol;
}
print(formattedList(data));
}

dart flutter max value from list of objects

Looking for some help how to select oldest age from users in flutter object list...
users = [
{ id: 123, name: 'Bob', age: 25},
{ id: 345, name: 'Joe', age: 44},
...
];
First make sure your list has the correct type and format:
List<Map<String, dynamic>> users = [
{"id": 123, "name": "Bob", "age": 25},
{"id": 345, "name": "Joe", "age": 44},
{"id": 35, "name": "Joxe", "age": 40},
];
Then you can do this:
if (users != null && users.isNotEmpty) {
users.sort((a, b) => a['age'].compareTo(b['age']));
print(users.last['age']);
}
Another way would be:
if (users != null && users.isNotEmpty) {
dynamic max = users.first;
users.forEach((e) {
if (e['age'] > max['age']) max = e;
});
print(max['age']);
}
Another one:
if (users != null && users.isNotEmpty) {
print(users.fold<int>(0, (max, e) => e['age'] > max ? e['age'] : max));
}
And this one requires import 'dart:math':
if (users != null && users.isNotEmpty) {
print(users.map<int>((e) => e['age']).reduce(max));
}
I'd use the list reduce function, docs here.
var oldestUser = users.reduce((currentUser, nextUser) => currentUser['age'] > nextUser['age'] ? currentUser : nextUser)
void main() {
var users = [
{"id": 123, "name": 'Bob', "age": 25},
{"id": 345, "name": 'Joe', "age": 44},
{"id": 35, "name": 'Joxe', "age": 40},
];
users.sort(ageCompare);
print(users.first);
}
int ageCompare(u1, u2) => u2['age'] - u1['age'];
try it on https://dartpad.dartlang.org
or just one-liner
users.sort((Map u1, Map u2) => u2['age'] - u1['age']);
print(users.first);

How to rearrange map keys in dart?

I have a map like below :
{
"Future": [
{
"accountId": 57,
"firstName": "Inez",
"lastName": "Mitchell",
"middleName": "J",
}
],
"Overdue": [
{
"accountId": 5,
"firstName": "Mak",
"lastName": "Mitchell",
"middleName": "M",
}
],
"Due Today": [
{
"accountId": 59,
"firstName": "Jack",
"lastName": "Daniel",
"middleName": "P",
}
]
}
and wanted the map like in below order, Due Today first, Overdue 2nd and Future at last.
{
"Due Today": [
{
"accountId": 59,
"firstName": "Jack",
"lastName": "Daniel",
"middleName": "P",
}
],
"Overdue": [
{
"accountId": 5,
"firstName": "Mak",
"lastName": "Mitchell",
"middleName": "M",
}
],"Future": [
{
"accountId": 57,
"firstName": "Inez",
"lastName": "Mitchell",
"middleName": "J",
}
]
}
also these keys in length are 3 but sometimes we got only two of them means Due Today and Future but we have to make sure order is like 1. Due Today 2. Overdue 3. Future
There is no operation which simply rearranges the iteration order of a normal Dart map.
Dart maps usually default to using LinkedHashMap which orders its element (for example for iteration) in key insertion order.
If a key is already there, changing its value does not change the key's position in the iteration order, but any new key added will end up after all existing keys.
That provides the only avaialble way to change iteration order: Remove the key and add it again, which will put it at the end of the iteration order instead of where it previously was.
So, to reorder a map, the easiest is to create a new map:
var newMap = <String, List<Map<String, String>>>{};
for (var key in ["Due Today", "Overdue", "Future"]) {
if (map.containsKey(key)) newMap[key] = map[key];
}
Then newMap has the keys in the correct order. If you want to update your existing map to the same order, then you can do: map..clear()..addAll(newMap); afterwards.
If you want to avoid the extra map, you can delete keys and re-add them instead.
for (var key in ["Due Today", "Overdue", "Future"]) {
if (map.containsKey(key)) {
var value = map[key];
map.delete(key);
map[key] = value;
}
}
This should remove and re-add each key, if it's there at all, in the order you want them.
var keys = abc.keys.toList()..shuffle();
for(var k in keys) {
print('$k, ${abc[k]}');}
steps you need todo:
convert the map to a temp list
do your edits on the list
clear the map
copy the entries from the list back to map
**
> extension ExtensionsOnMap on Map<String, ChannelItem> {
> void replace(int index, String key, ChannelItem channelItem) {
>
> var tmpLst = this.entries.map((e) => MapEntry(e.key, e.value)).toList();
>
> tmpLst.removeAt(index);
> tmpLst.insert(index, new MapEntry(key, channelItem));
>
> this.clear();
>
> tmpLst.forEach((mapEntry) => this[mapEntry.key] = mapEntry.value);
> }
> }
**
Code:
void main(){
Map map = {
"Future": [
{
"accountId": 57,
"firstName": "Inez",
"lastName": "Mitchell",
"middleName": "J",
}
],
"Overdue": [
{
"accountId": 5,
"firstName": "Mak",
"lastName": "Mitchell",
"middleName": "M",
}
],
"Due Today": [
{
"accountId": 59,
"firstName": "Jack",
"lastName": "Daniel",
"middleName": "P",
}
]
};
for(String key in ['Due Today', 'Overdue', 'Future']){
var value = map[key];
map.remove(key);
map[key] = value;
}
print(map);
}
Output:
{
Due Today: [{
accountId: 59,
firstName: Jack,
lastName: Daniel,
middleName: P
}],
Overdue: [{
accountId: 5,
firstName: Mak,
lastName: Mitchell,
middleName: M
}],
Future: [{
accountId: 57,
firstName: Inez,
lastName: Mitchell,
middleName: J
}]
}

MongoDB : getting list of values by using Group

I have a collection called contract and I would like to group using "a_id"
{
a_id: 1,
"name": "n1"
}
{
a_id: 2,
"name": "n2"
}
{
a_id: 1,
"name": "n3"
}
{
a_id: 1,
"name": "n4"
}
{
a_id: 2,
"name": "n5"
}
I want to group by "a_id" to show me the list of names associated.
{
a_id: 1,
values: ["n1", "n3", "n4"]
}
{
a_id: 2,
values: ["n2", "n5"]
}
My code:
db.contract.group({
key:{a_id: 1},
initial: {v: ''},
reduce: function(doc, obj){
v = v + " " + obj.name
}
});
My Output:
{
"a_id" : 1,
"v" : ""
},
{
"asset_id" : 2,
"v" : ""
}
This doesn't return the list of values, but mongd logs shows me list of names, How can I correct this?
Fixed
db.contract.group({
key:{a_id: 1},
initial: {v: []},
reduce: function(obj, prev){
prev.v.push(obj.name)
}
});
You could also use MongoDB's aggregation framework:
The following will work exactly the same:
db.contract.aggregate({$group: { '_id': '$a_id', 'name': { $push: '$name'}}})
The following will put every unique value only once in the result set (in case there are duplicated names per 'a_id'):
db.contract.aggregate({$group: { '_id': '$a_id', 'name': { $addToSet: '$name'}}})
Fixed
db.contract.group({
key:{a_id: 1},
initial: {v: []},
reduce: function(obj, prev){
prev.v.push(obj.name)
}
});