Filter and manipulate a map - flutter

It's the first time I use Dart and I'm stuck with a simple thing.
I have a simple Map and I need to remove some items from this map and modify the content.
I have this:
Map<String, List<String>> dataset = {
'apple': ['apple1', 'apple2', 'apple3'],
'pear': ['pear1', 'pear2'],
'ananas': ['ananas1', 'ananas2', 'ananas3'],
'orange': ['orange1', 'orange2', 'orange3', 'orange4'],
};
List<Map<dynamic, String>> fruits = [
{'key': 'pear', 'labelToShow': 'Pear fruit'},
{'key': 'ananas', 'labelToShow': 'My ananas'},
];
and I would like to have this:
Map<String, Map<String, List<String>>> result = {
'pear': {
'values': ['pear1', 'pear2'],
'labelToShow': 'Pear fruit'
},
'ananas': {
'values': ['ananas1', 'ananas2', 'ananas3'],
'labelToShow': 'My ananas'
},
};
So, basically, I need to remove from dataset the items that have the key that it's not included in fruits (in field key) and then I need to add the field labelToShow.
I dont' know ho to do that.
I started removing items from dataset doing so:
dataset.removeWhere((k, v) => k != 'pear' && k != 'ananas');
but I don't like, I would like to loop through fruits.
Can someone please help me?
Thanks a lot

I wouldn't remove anything from dataset. Instead I'd build a new map from scratch, with just the data you want.
How about:
Map<String, Map<String, List<String>>> result = {
for (var fruit in fruits)
fruit["key"]: {
"values": dataset[fruit["key"]],
"labelToShow": fruit["labelToShow"]
}
};

Related

how to add and edit data at the same time into local list

i have these fields from Firstore doc
'name': 'Alex'
'age': 20
'product': 'cars'
and here i get data
List <QueryDocumentSnapshot> finalResultsForMessgse = [] ;
future getData(){
FirebaseFirestore.instance.collection("product").get().then((value) {
value.docs.forEach((data) {
finalResultsForMessgse.add(data); // here it will add data as written
exactly in firstore into my local list
but how can manual edit fields into my local list ..like following
finalResultsForMessgse.add(
'name':value.get('name')+'add extra Letters'
'age':value.get('age')+'add extra Letters'
'product':value.get('product')+'add extra Letters'
)
use List<dynamic> finalResultsForMessgse = []; for final result list.
FirebaseFirestore.instance.collection('product').get().then((value) {
value.docs.forEach((data) {
var doc = data.data();
finalResultsForMessgse.add({
'name': '${doc['name']} + add extra Letters',
'age': '${doc['age']} + add extra Letters',
'product': '${doc['product']} + add extra Letters',
});
});
});
To show the result list:
for (var item in finalResultsForMessgse) Text('${item['name']}'),

How to remove an item from list of maps based on specific key?

I have the following list
List<Map<String, dynamic>> filterItems = [
{"category":1},
{"option_val":1},
]
I also have the following map
Map<String, dynamic> singleItem = {"category":6}
I would like to remove any item from the list above (filterItems) which has an object with key similar to singleItem map. So in my case i would like to remove the {"category":1} from the list since it has a key category similar to the map.
So i have tried the following
filterItems.remove(singleItem);
print(filterItems)
But the above doesnt work since the value of key is different so i tried the following where am now stuck on how to proceed
singleItem.map((key,value){
filterItems.removeWhere((element) => element.containsKey(key))
})
But the above throws an error that the body of singleItem.map is returning null. How can I proceed to remove an item from the list when a key matches even though the value is different?
you can use .removeWhere as follow:
List<Map<String, dynamic>> filterItems = [
{"category":1},
{"option_val":1},
];
Map<String, dynamic> singleItem = {"category":6};
filterItems.removeWhere((element) => element.keys.first == singleItem.keys.first);
print(filterItems);
and the result would be:
[{option_val: 1}]
Remove when a list has the same key
List<Map<String, dynamic>> filterItems = [
{"category": 1},
{"option_val": 1},
];
Map<String, dynamic> singleItem = {"category": 6};
filterItems = filterItems.where((e) {
return e.keys.toString() != singleItem.keys.toString();
}).toList();

How to search a list of Object by another list of items in dart

How to search a list of a class object with one of its property matching to any value in another list of strings
I am able to get filtering based on a single string , but not on a list of strings
final List<shop_cart.ShoppingCart> cartprd = snapshot.documents
.map((f) => shop_cart.ShoppingCart.fromMap(f.data))
.toList();
List<SomeClass> list = list to search;
List<String> matchingList = list of strings that you want to match against;
list.where((item) => matchingList.contains(item.relevantProperty));
If the number of items in list is large, you might want to do:
List<SomeClass> list = list to search;
List<String> matchingList = list of strings that you want to match against;
final matchingSet = HashSet.from(matchingList);
list.where((item) => matchingSet.contains(item.relevantProperty));
Or else just always store the matching values as a hashset.
In case if you want to check for a value in a list of objects . you can follow this :
List rows = [
{"ags": "01224", "name": "Test-1"},
{"ags": "01224", "name": "Test-1"},
{"ags": "22222", "name": "Test-2"},
];
bool isDataExist(String value) {
var data= rows.where((row) => (row["name"].contains(value)));
if(data.length >=1)
{
return true;
}
else
{
return false;
}
}
you can put your own array of objects on rows . replace your key with name . you can do your work based on true or false which is returned from the function isDataExist
As of today, you can't.
(A side note : You can use .where, .singleWhere, .firstWhere. This site explains various list/array methods.)
You can simply use List.where() to filter a list
final List<shop_cart.ShoppingCart> cartprd = snapshot.documents
.where((f) => shop_cart.ShoppingCart.contains(f.data));
var one = [
{'id': 1, 'name': 'jay'},
{'id': 2, 'name': 'jay11'},
{'id': 13, 'name': 'jay222'}
];
int newValue = 13;
print(one
.where((oldValue) => newValue.toString() == (oldValue['id'].toString())));
OUTPUT : ({id: 13, name: jay222})
store output in any variable check if variable.isEmpty then new value is unique either
var checkValue = one
.where((oldValue) => newValue.toString() == (oldValue['id'].toString()))
.isEmpty;
if (checkValue) {
print('Unique');
} else {
print('Not Unique');
}
OUTPUT : Not Unique

Dart how to access second dimension in multidimensional map

I can manage to access the first dimension with mymap['status'] but I tried to access the second dimension with mymap['status'].start or mymap['status']['start'] but neither work.
Also I don't see why mymap.status doesn't work for the first dimension?
const mymap = {
'status': {
'start': ['Start', 'ok', 'go'],
},
'update': {
'now': ['Start', 'ok', 'go'],
},
'time': [
['20', '10s', '5s'],
['45', '30s', '15s']
]
};
Also not sure whether this map should have the data type Map or not but with it I get no error signal with mymap['status'].start but upon executing the code it throws the error Class '_ImmutableMap<String, List<String>>' has no instance getter 'start'
To fix your issue use a static type Map after const , like this :
const Map mymap = {
'status': {
'start': ['Start', 'ok', 'go'],
},
'update': {
'now': ['Start', 'ok', 'go'],
},
'time': [
['20', '10s', '5s'],
['45', '30s', '15s']
]
};
print(mymap['status']['start']);
You can run the code if you want https://dartpad.dartlang.org/20eab4288fbf688c6517365b89fc2b22
You look up values for keys in a Dart Map using map[key]. If the key is a string, that would be mymap["status"]. You cannot use mymap.status because map keys are completely separate from class members. That's why you can do both map["length"] and map.length and get different results.
In your example, the static type of mymap is inferred to be Map<String, Object>.
This is inferred because the values of your map are either Map<String, List<String>> (for "status" and "update") or List<List<String>> (for "time"). The only common supertype of Map and List is Object, so your map is a Map<String, Object>.
When you then write mymap['status'] you get an expression with static type Object, and you are not allowed to do ['start'] on that (Object does not have an [] operator).
If you type your variable as Map<String, dynamic>, then you are allowed to do mymap['status']['start']. The final index operation is a dynamic invocation, which comes at some run-time cost.
Alternatively, you can do (mymap['status'] as Map<String, List<String>>)['start'] which casts the looked-up value to a map of the correct type, and then does a well-typed lookup on the that map.

Parsing JSON effectively in Flutter/Dart

How to extract a pair of values out of a JSON using dart
This is the function I have so far:
This is the JSON:
{
"displayNames": [
"John Doe",
"ChloƩ Kamgang",
"Lady Testing of Tarth"
],
"users": [
{
"uid": "1tcPRqNZ7wexX2DWa11V9Ay1zES2",
"displayName": "John Doe"
},
{
"uid": "aZg7Emp8H9W42irnM73NBdTe6YM2",
"displayName": "ChloƩ Kamgang",
"photoURL": "https://firebasestorage.googleapis.com/v0/b/atalaku-fcf9e.appspot.com/o/Profilescaled_1e189635-0bc0-4791-ba20-6aded7ad3e8f7210544.jpg621jpg?alt=media&token=f5cffac3-a20c-4a83-8241-4fab16a9bd66"
},
{
"uid": "hXzyTuDE8eafnSxITmz7ZdMQDnw1",
"displayName": "Lady Testing of Tarth",
"photoURL": "https://firebasestorage.googleapis.com/v0/b/atalaku-fcf9e.appspot.com/o/Profilescaled_image_picker8162975920.jpg645jpg?alt=media&token=269007d1-09ee-4fe4-b7ad-72aa7cea756a"
}
]
}
And this is the function:
Future<List<Map<String, dynamic>>> getProfilesBySuggestion(
String sSuggestion) async {
try {
List<Map<String, dynamic>> listToReturn = [];
if (sSuggestion == null ||
sSuggestion.isEmpty ||
!sSuggestion.startsWith('#')) return listToReturn;
//Getting all the names
Map<String, dynamic> listUsers = await getAllUsers();
if (listUsers == null) return listToReturn;
//Returning only the names corresponding
List<dynamic> listNames = listUsers['displayNames'];
for (String name in listNames)
if (name
.toLowerCase()
.startsWith(sSuggestion.substring(1).toLowerCase())) {
List<Map<String, dynamic>> listOfusers = listUsers['users'] as List<Map<String, dynamic>>;
Map<String, dynamic> rightOne = listOfusers.firstWhere((user) => user['displayName'] == name);
String sPhotoURL = rightOne['photoURL'];
print('** name = $name, photoURL = $sPhotoURL');
listToReturn.add({'name': name, 'photoURL': sPhotoURL});
}
return listToReturn;
} catch (error) {
print('*** Error During getProfilesBySuggestion: ${error.toString()}');
return [
{'errorMessage': error.toString()}
];
}
}
What I want is a list of pair (name, photoURL). I am using the flutter_typeahead plugin, I want to display a list of names and their respective avatars. As you can see, I am using Firebase. Please let me know if there is a better option as well, as this will get pretty heavy with scale. Thank you!
A good starting point when working with data that's not organised the way you want it, is to re-organize it. I'd merge the two lists adding the display name to each user. But, of course, you see immediately that that's not necessary as each user already contains their display name. (The displayNames branch of your json is unnecessary for your purposes.)
So, you can just work with the users branch. Note that what you are doing is extracting the members of the users list and subtly changing the tag name (from displayName to name - leaving photoURL the same). Is the tag name change necessary? If not you could basically achieve what you want with a single where.
That said, this should achieve what you want (including the tag name change):
Future<List<Map<String, dynamic>>> getProfilesBySuggestion(
String sSuggestion) async {
try {
if (sSuggestion == null ||
sSuggestion.isEmpty ||
!sSuggestion.startsWith('#')) return [];
//Getting all the names
Map<String, dynamic> allUsers = await getAllUsers();
if (allUsers == null) return [];
//Returning only the names corresponding
List<dynamic> users = allUsers['users'];
var suffix = sSuggestion.substring(1).toLowerCase();
return users
.where((user) => user['displayName'].toLowerCase().startsWith(suffix))
.map<Map<String, dynamic>>((user) => {
'name': user['displayName'],
'photoURL': user['photoURL'],
})
.toList();
} catch (error) {
print('*** Error During getProfilesBySuggestion: ${error.toString()}');
return [
{'errorMessage': error.toString()}
];
}
}
A good starting point when working with data that's not organised the way you want it, is to re-organize it.
And if that's not an option, you can still mitigate the impact. It's always easier to work with plain old dart classes than json, so I'd encourage you to map the json to classes.
I usually use package:built_value for that. There is a tool that helps map json:
https://charafau.github.io/json2builtvalue/ Careful, it's not 100%. Eg. it will not include photoUrl field if you just copy-paste your json.
Basically, I'd take the json.users, and map it to objects. Make sure to make photoUrl optional.
Once that's done, you can create any lookup table you want. You could just have a List<User> to iterate over names and photoUrls, or you could create a Map<String, User> to look up users by their name.
Tip: class Map has got a number of constructors that you can work with.