英文:
Duplicate entry in List of ListTiles - Flutter
问题
I am trying to add items to a 'cart' list from my interface and see that for specific items, adding a different item produces a duplicate entry.
List<Widget> _subSubExpansionTiles(BuildContext context, List<Item> itemSubList) {
// this makes the second level of ExpansionTiles - the item, i.e. "Regular", "Starch" etc
List<Widget> _subSubList = [];
var groupedActionLists = groupBy(itemSubList, (Item item) => item.service);
//print(groupedActionLists.keys.toList());
Map<String, Map<String, dynamic>> counter = {};
print("*************************${groupedActionLists.keys} ****************************************");
for(var key in groupedActionLists.keys) { // Wash And Fold, Wash And Iron
//print("$key : ${groupedActionLists[key]!.length.toString()}");
print("*************$key : ${groupedActionLists[key]!.length} ******************");
Map<String, dynamic> subMap = {};
int regular = 0;
int regularStarch = 0;
int stainRemoval = 0;
int stainRemovalStarch = 0;
for(Item item in groupedActionLists[key]!) {
if (item.starch == null && item.stainRemoval == null) {
regular++;
}
else if (item.starch != null && item.stainRemoval == null) {
if (item.starch == false) {
regular++;
} else {
regularStarch++;
}
}
else if (item.starch == null && item.stainRemoval != null) {
if (item.stainRemoval == false) {
regular++;
} else {
stainRemoval++;
}
}
else if (item.starch != null && item.stainRemoval != null) {
if (item.starch == false && item.stainRemoval == false) {
regular++;
} else if (item.starch == true && item.stainRemoval == false) {
regularStarch++;
} else if (item.starch == false && item.stainRemoval == true) {
stainRemoval++;
} else if (item.starch == true && item.stainRemoval == true) {
stainRemovalStarch++;
}
}
subMap.addEntries({'regular' : regular}.entries);
subMap.addEntries({'regularStarch' : regularStarch}.entries);
subMap.addEntries({'stainRemoval' : stainRemoval}.entries);
subMap.addEntries({'stainRemovalStarch' : stainRemovalStarch}.entries);
counter.addEntries({item.service! : subMap}.entries);
};
//print(counter);
String prevKey = "";
for(var key in counter.keys){
print("Iterating through $key");
for (var subkey in counter[key]!.keys) {
//print("${counter[key]!.keys}");
String nameString = '';
if (subkey == 'regular')
nameString = key;
else if (subkey == 'regularStarch')
nameString = key + '+ Starch';
else if (subkey == 'stainRemoval')
nameString = key + '+ Stain Removal';
else if (subkey == 'stainRemovalStarch') nameString = key + '+ Stain Removal + Starch';
if (counter[key]![subkey] > 0) {
print("adding : $nameString");
_subSubList.add(ListTile(
title: Text(nameString),
visualDensity: VisualDensity.compact,
leading: Padding(padding: EdgeInsets.fromLTRB(5, 0, 5, 0)),
trailing: Text(
counter[key]![subkey].toString(),
style: const TextStyle(
fontSize: 15,
),
)));
}
//print("$key : ${counter[key]![subkey]}");
}
}
}
//print("returning $_subSubList");
return (_subSubList);
}
I get the following output, where as we can see 'Wash and Iron' is repeated twice. The converse is also true - when I add Wash and Fold first and then Wash and Iron, I see Wash and Fold twice.
Here the Item class has the following members:
class Item implements Jsonifyable {
String? id;
String? item;
String? image;
String? action;
String? service;
bool? starch;
bool? stainRemoval;
Item({
this.id,
this.item,
this.image,
this.action,
String? service,
this.starch,
this.stainRemoval,
})
[![Screenshot][1]][1]
I've added debug statements to understand what is going on and I get:
Reloaded 8 of 1506 libraries in 1,799ms (compile: 202 ms, reload: 546 ms, reassemble: 1026 ms).
I/flutter (10344): *************************(Wash and Iron, Wash and Fold) ****************************************
I/flutter (10344): *************Wash and Iron : 1 ******************
I/flutter (10344): Iterating through Wash and Iron
I/flutter (10344): adding : Wash and Iron
I/flutter (10344): *************Wash and Fold : 1 ******************
I/flutter (10344): Iterating through Wash and Iron
I/flutter (10344): adding : Wash and Iron
I/flutter (10344): Iterating through Wash and Fold
I/flutter (10344): adding : Wash and Fold
Here the _subsublist function is invoked by the following functions:
List<Widget> _subExpansionTiles(BuildContext context, List<Item> itemList) {
// this makes the first level of ExpansionTiles - the item, i.e. "Shirt", "Trouser" etc
String action = itemList[0].action!;
List<Widget> itemTiles = [];
var groupedIdLists = groupBy(itemList, (Item item) => item.id);
// we get {'S001' : [], 'S002' : [] ... etc ... }
groupedIdLists.forEach((key, value) {
List<Item> _subItemList = value;
String itemName = _subItemList[0].item!;
var tile = ExpansionTile(
title: Text(itemName),
subtitle: Text('Click to expand'),
controlAffinity: ListTileControlAffinity.leading,
maintainState: true,
trailing: Text(
_subItemList.length.toString(),
style: const TextStyle(
fontSize: 20,
),
),
children: _subSubExpansionTiles(context, _subItemList));
itemTiles.add(tile);
});
return itemTiles;
}
Widget _buildExpansionTiles(BuildContext context, String category) {
// this makes the first level of ExpansionTiles - the item, i.e. "Iron", "Dry Clean", etc
if (!cartItems.containsKey(category)) {
return SliverToBoxAdapter(child: Container());
}
List<Item> _categoryItems = cartItems[category]
<details>
<summary>英文:</summary>
I am trying to add items to a 'cart' list from my interface and see that for specific items, adding a different item produces a duplicate entry.
List<Widget> _subSubExpansionTiles(BuildContext context, List<Item> itemSubList) {
// this makes the second level of ExpansionTiles - the item , i.e. "Regular", "Starch" etc
List<Widget> _subSubList = [];
var groupedActionLists = groupBy(itemSubList, (Item item) => item.service);
//print(groupedActionLists.keys.toList());
Map<String, Map<String, dynamic>> counter = {};
print("*************************${groupedActionLists.keys} ****************************************");
for(var key in groupedActionLists.keys) { // Wash And Fold, Wash And Iron
//print("$key : ${groupedActionLists[key]!.length.toString()}");
print("*************$key : ${groupedActionLists[key]!.length} ******************");
Map<String, dynamic> subMap = {};
int regular = 0;
int regularStarch = 0;
int stainRemoval = 0;
int stainRemovalStarch = 0;
for(Item item in groupedActionLists[key]!) {
if (item.starch == null && item.stainRemoval == null) {
regular++;
}
else if (item.starch != null && item.stainRemoval == null) {
if (item.starch == false) {
regular++;
} else {
regularStarch++;
}
}
else if (item.starch == null && item.stainRemoval != null) {
if (item.stainRemoval == false) {
regular++;
} else {
stainRemoval++;
}
}
else if (item.starch != null && item.stainRemoval != null) {
if (item.starch == false && item.stainRemoval == false) {
regular++;
} else if (item.starch == true && item.stainRemoval == false) {
regularStarch++;
} else if (item.starch == false && item.stainRemoval == true) {
stainRemoval++;
} else if (item.starch == true && item.stainRemoval == true) {
stainRemovalStarch++;
}
}
subMap.addEntries({'regular' : regular}.entries);
subMap.addEntries({'regularStarch' : regularStarch}.entries);
subMap.addEntries({'stainRemoval' : stainRemoval}.entries);
subMap.addEntries({'stainRemovalStarch' : stainRemovalStarch}.entries);
counter.addEntries({item.service! : subMap}.entries);
};
//print(counter);
String prevKey = "";
for(var key in counter.keys){
print("Iterating through $key");
for (var subkey in counter[key]!.keys) {
//print("${counter[key]!.keys}");
String nameString = '';
if (subkey == 'regular')
nameString = key;
else if (subkey == 'regularStarch')
nameString = key + '+ Starch';
else if (subkey == 'stainRemoval')
nameString = key + '+ Stain Removal';
else if (subkey == 'stainRemovalStarch') nameString = key + '+ Stain Removal + Starch';
if (counter[key]![subkey] > 0) {
print("adding : $nameString");
_subSubList.add(ListTile(
title: Text(nameString),
visualDensity: VisualDensity.compact,
leading: Padding(padding: EdgeInsets.fromLTRB(5, 0, 5, 0)),
trailing: Text(
counter[key]![subkey].toString(),
style: const TextStyle(
fontSize: 15,
),
)));
}
//print("$key : ${counter[key]![subkey]}");
}
}
}
//print("returning $_subSubList");
return (_subSubList);
}
I get the following output, where as we can see 'Wash and Iron' is repeated twice. The converse is also true - when I add Wash and Fold first and then Wash and Iron, I see Wash and Fold twice.
Here the Item class has the following members:
class Item implements Jsonifyable {
String? id;
String? item;
String? image;
String? action;
String? service;
bool? starch;
bool? stainRemoval;
Item({
this.id,
this.item,
this.image,
this.action,
String? service,
this.starch,
this.stainRemoval,
})
[![Screenshot][1]][1]
I've added debug statements to understand what is going on and I get:
Reloaded 8 of 1506 libraries in 1,799ms (compile: 202 ms, reload: 546 ms, reassemble: 1026 ms).
I/flutter (10344): *************************(Wash and Iron, Wash and Fold) ****************************************
I/flutter (10344): *************Wash and Iron : 1 ******************
I/flutter (10344): Iterating through Wash and Iron
I/flutter (10344): adding : Wash and Iron
I/flutter (10344): *************Wash and Fold : 1 ******************
I/flutter (10344): Iterating through Wash and Iron
I/flutter (10344): adding : Wash and Iron
I/flutter (10344): Iterating through Wash and Fold
I/flutter (10344): adding : Wash and Fold
Here the _subsublist function is invoked by the following functions:
List<Widget> _subExpansionTiles(BuildContext context, List<Item> itemList) {
// this makes the first level of ExpansionTiles - the item , i.e. "Shirt", "Trouser" etc
String action = itemList[0].action!;
List<Widget> itemTiles = [];
var groupedIdLists = groupBy(itemList, (Item item) => item.id);
// we get {'S001' : [], 'S002' : [] ... etc ... }
groupedIdLists.forEach((key, value) {
List<Item> _subItemList = value;
String itemName = _subItemList[0].item!;
var tile = ExpansionTile(
title: Text(itemName),
subtitle: Text('Click to expand'),
controlAffinity: ListTileControlAffinity.leading,
maintainState: true,
trailing: Text(
_subItemList.length.toString(),
style: const TextStyle(
fontSize: 20,
),
),
children: _subSubExpansionTiles(context, _subItemList));
itemTiles.add(tile);
});
return itemTiles;
}
Widget _buildExpansionTiles(BuildContext context, String category) {
// this makes the first level of ExpansionTiles - the item , i.e. "Iron", "Dry Clean", etc
if (!cartItems.containsKey(category)) {
return SliverToBoxAdapter(child: Container());
}
List<Item> _categoryItems = cartItems[category]!;
if (_categoryItems.length == 0) return SliverToBoxAdapter(child: Container());
String action = _categoryItems[0].action!;
return SliverToBoxAdapter(
child: ExpansionTile(
title: Text(action),
subtitle: Text('Click to expand'),
controlAffinity: ListTileControlAffinity.trailing,
maintainState: true,
leading: Text(
_categoryItems.length.toString(),
style: const TextStyle(
fontSize: 25,
),
),
children: _subExpansionTiles(context, _categoryItems),
),
);
}
Can anyone help me figure out why there is a duplicate entry?
[1]: https://i.stack.imgur.com/D5zND.png
</details>
# 答案1
**得分**: 1
把以下这行代码:
Map<String, Map<String, dynamic>> counter = {};
移动到以下这行代码下面:
for (var key in groupedActionLists.keys) { // Wash And Fold, Wash And Iron
因为现在当它到达循环中的第二个键时,`counter` 仍然被前一个循环填充。将其移动到循环内部会从一个空的计数器开始。
<details>
<summary>英文:</summary>
I'm not entirely sure but I believe you need to move the line
Map<String, Map<String, dynamic>> counter = {};
to below the line
for(var key in groupedActionLists.keys) { // Wash And Fold, Wash And Iron
because now when it reaches the second key in the loop the `counter` is still filled by the previous loop. By moving it inside the loop it starts with a empty counter.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论