I am trying to remove map item based on key. So, I read documentation about using .remove(key). However it return error. Here is my code
Future<bool> UpdateFilter() async{
_selectedFilter['category'] = _category!=null ? _category : '';
_selectedFilter['subCategory'] = _subCategory!=null ? _subCategory : '';
_selectedFilter['type'] = _type;
_selectedFilter['price'] = _price.end.round() > 0 ? [_price.start.round(),_price.end.round()] : [];
_selectedFilter['bedroom'] = _bedroom.round();
_selectedFilter['bathroom'] = _bathroom.round();
_selectedFilter['lt'] = _landSize.end.round() > 0 ? [_landSize.start.round(),_landSize.end.round()] : [];
_selectedFilter['lb'] = _buildingSize.end.round() > 0 ? [_buildingSize.start.round(),_buildingSize.end.round()] : [];
//check for empty values then remove from filter
_selectedFilter.forEach((key, value) {
if(_selectedFilter[key].runtimeType == int && _selectedFilter[key]==0){
_selectedFilter.remove(key); ===> does not work, consist errors
}
else if(_selectedFilter[key].isEmpty){
_selectedFilter.remove(key); ===> does not work, consist errors
}
});
_selectedFilter.remove('bedroom'); ===> it works without foreach (manually), for testing purpose
_selectedFilter.remove('bathroom'); ===> it works without foreach (manually), for testing purpose
return true;
}
Here is the error logs
[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: Concurrent modification during iteration: _LinkedHashMap len:7. #0 _CompactIterator.moveNext (dart:collection-patch/compact_hash.dart:615:7) #1 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:537:15) #2 _SearchState.UpdateFilter (package:rumahkita/pages/search.dart:65:21) #3 _SearchState.build.. (package:rumahkita/pages/search.dart:429:23) #4 State.setState (package:flutter/src/widgets/framework.dart:1121:30) #5 _SearchState.build. (package:rumahkita/pages/search.dart:428:21) #6 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:989:21) #7 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:198:24) #8 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:608:11) #9 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:296:5) #10 Bas<…>
Does anyone know why it could happen? It works when I tried to do manual remove but if it is inside loop function, it cause an error.
CodePudding user response:
You're attempting to call _selectedFilter.remove
from within a callback to _selectedFilter.forEach
. As stated from the Map.forEach
documentation:
Calling
action
must not add or remove keys from the map.
In general, mutating the collection you're currently iterating over usually is asking for trouble (unless the documentation explicitly says that it is allowed), because who knows how iteration will proceed? If you add an item, will you iterate over the added item? What if you added or removed an item at a position you already iterated over? If you removed the current item, what should the next item be? If you removed the current item and then added it back, should you iterate over that item again? And so on.
A general approach to deal with this kind of thing is to keep a separate queue of actions to perform, and then perform them separately after you finish iterating over the collection:
var keysToRemove = <String>[];
_selectedFilter.forEach((key, value) {
if ((_selectedFilter[key] is int && _selectedFilter[key] == 0) ||
_selectedFilter[key].isEmpty) {
keysToRemove.add(key);
}
});
for (var key in keysToRemove) {
_selectedFilter.remove(key);
}
CodePudding user response:
You are looping over _selectedFilter
's entries (with _selectedFilter.forEach(/* ... */)
).
When you are looping over the entries, you cannot remove/add entries at the same time because it is not obvious what should happen.
Let's say you are looping over the list [0, 1, 2]
(this is the same as for maps):
final list = [0, 1, 2];
for (final i in list) {
if (i == 1) {
list.push(3);
}
}
It is not clear what should happen, should i
be equal to 3
at some point, or should it stop to 2
?
If you only want to remove some entries that match a condition you can use
_selectedFilter.removeWhere((key, value) {
/* Your condition */
});