Reorder Array of objects Flutter - flutter

Array of object
Input:
[
{id:1,order:1},
{id:2,order:null},
{id:3,order:0},
{id:4,order:null},
{id:5,order:3}
]
Output:
[
{id:3,order:0},
{id:1,order:1},
{id:2,order:null},
{id:5,order:3},
{id:4,order:null}
]
Considering model
Item(int id,int? Order)
By default the order is null and these positions are to be maintained and object having orders are to be moved up or down.

Try this, if the array is of type Map -
arrayOfObjects.sort((a, b) => a['order'].compareTo(b['order']));
Or this if it is holding Item class with an order attribute
arrayOfObjects.sort((Item a, Item b) => a.order.compareTo(b.order));
Note - You can remove items with null order before running the sort.
Example
arrayOfObjects.removeWhere((item)=> item.order == null);

The double Iterations are based on the length of the array to handle the nulls.
Solution
import 'package:collection/collection.dart';
class Item {
int? _id;
int? _order;
Item({int? id, int? order}) {
this._id = id;
this._order = order;
}
int? get id => _id;
set id(int? id) => _id = id;
int? get order => _order;
set order(int? order) => _order = order;
Item.fromJson(Map<String, dynamic> json) {
_id = json['id'];
_order = json['order'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this._id;
data['order'] = this._order;
return data;
}
}
List<Item> reorder(List<Item> it){
var tempData = it;
tempData.forEach((_){
tempData.forEachIndexed((index,val){
///Remove original and replace
var ind = val.order;
if(ind!=null){
///Check if it is at the Proper Position
if (index == ind) {
return;
}
var first = it.removeAt(index);
it.insert(ind as int, first);
}
});
});
return it;
}
void main() {
var list = [
Item(id: 1, order: 1),
Item(id: 3, order: 2),
Item(id: 2, order: 7),
Item(id: 4, order: null),
Item(id: 5, order: null),
Item(id: 6, order: null),
Item(id: 7, order: 6),
Item(id: 8, order: 4)
];
list.forEach((it) => print('${it.id} ->${it.order}'));
var first = reorder(list);
print('\n');
first.forEach((it) => print('${it.id} ->${it.order}'));
///Stack List
}

Related

how to filter data based on tag in flutter?

I am creating a screen where need to filter data based on category types and transaction type.
Its working fine but it results null when filter list is empty, I can manage with some logically tricks but it will be lengthy coding..
is there any other better way to filter data properly even if filter tag is empty and
should display all records based on transaction type
like
transactiontype='Expense'
filtertags=[]
result:
it should display all expense transactions
transactiontype='Expense'
filtertags=['Food']
result:
it should display all expense transactions of Food
class TransactionModel {
String category;
double amount;
bool isExpense;
TransactionModel(
{required this.category, required this.amount, this.isExpense = true});
String printData() {
return 'Category:' +
category +
' Amount: ' +
amount.toString() +
'isExpense:' +
isExpense.toString();
}
}
List<String> _filtertags = ['Food'];// if this list is empty it should show all posible records
String transactiontype = 'Expense';
List<TransactionModel> transactions = [
TransactionModel(
category: 'Shopping',
amount: 4300,
),
TransactionModel(category: 'Food', amount: 2200,isExpense: true),
TransactionModel(category: 'Loan', amount: 400, isExpense: false),
TransactionModel(category: 'Food', amount: 300,isExpense: false),
TransactionModel(category: 'Other', amount: 100,isExpense: true),
];
void main() {
var resultdata = transactiontype == 'All'
? transactions
.where((element) => _filtertags.contains(element.category))
.toList()
: transactiontype == 'Expense'
? transactions
.where((element) =>
_filtertags.contains(element.category) &&
element.isExpense == true)
.toList()
: transactions
.where((element) =>
_filtertags.contains(element.category) &&
element.isExpense == false)
.toList();
for (var x in resultdata) {
print(x.printData());
}
}
You can simplify like
var result = [];
if (transactionType == 'All' || transactionType.isEmpty) {
result = transactions.toList();
} else {
bool isExpense = transactionType == 'Expense';
//add more filter when needed and comare with model class
result = transactions
.where((element) =>
_filterTags.contains(element.category) &&
element.isExpense == isExpense)
.toList();
}
for (var x in result) {
print(x.toString());
}
});

Dart - How to merge two list of objects into singe list

2> as you can see below i have two list of object and i want to merge into single it should compare list based on date
//here is the list 1
List<Object1> list1=[
Object1("date":"1","day_data":12),
Object1("date":"2","day_data":15),
]
//here is the list 2
List<Object2> list2=[
Object2("date":"1","night_data":56),
Object2("date":"3","night_data":80),
];
//expected output
List<Object3> expectedList=[
Object3("date":"1","day_data":12,"night_data":56),
Object3("date":"2","day_data":15,"night_data":null),
Object3("date":"3","day_data":null,"night_data":80),
];
The code below should do the trick. It uses a Map where the keys are, let's say, the Primary Key. And the values are the reduce from list1 and list2 (It even merges duplicated items by date from list1 and/or list2). At the end, I've added some asserts to actually test if it works.
Here's also the DartPad to run it online.
class Object1 {
final String date;
final int day_data;
const Object1({required this.date, required this.day_data});
}
class Object2 {
final String date;
final int night_data;
const Object2({required this.date, required this.night_data});
}
class Object3 {
final String date;
final int? day_data;
final int? night_data;
const Object3({required this.date, this.day_data, this.night_data});
}
List<Object3> merge(List<Object1> obj1List, List<Object2> obj2List) {
final map = <String, Object3>{};
obj1List.forEach((obj1) =>
map.update(
obj1.date,
(obj3) => Object3(date: obj3.date, day_data: obj1.day_data, night_data: obj3.night_data),
ifAbsent: () => Object3(date: obj1.date, day_data: obj1.day_data, night_data: null),
));
obj2List.forEach((obj2) =>
map.update(
obj2.date,
(obj3) => Object3(date: obj3.date, day_data: obj3.day_data, night_data: obj2.night_data),
ifAbsent: () => Object3(date: obj2.date, day_data: null, night_data: obj2.night_data),
));
return map.values.toList()
..sort((a, b) => a.date.compareTo(b.date));
}
void main() {
//here is the list 1
List<Object1> list1=[
Object1(date:"1",day_data:12),
Object1(date:"2",day_data:15),
];
//here is the list 2
List<Object2> list2=[
Object2(date:"1",night_data:56),
Object2(date:"3",night_data:80),
];
List<Object3> actualList = merge(list1, list2);
//expected output
List<Object3> expectedList=[
Object3(date:"1",day_data:12,night_data:56),
Object3(date:"2",day_data:15,night_data:null),
Object3(date:"3",day_data:null,night_data:80),
];
print('Checking size...');
assert(actualList.length == expectedList.length);
print('OK');
print('Checking items...');
actualList.asMap().forEach((i, actual) {
final expected = expectedList[i];
print(' Checking item $i...');
assert(actual.date == expected.date);
assert(actual.day_data == expected.day_data);
assert(actual.night_data == expected.night_data);
print(' OK');
});
print('OK');
}
You need to do manually with two loops and comparing dates.
Hey you can achieve by compering two list and get list like below -
void compareList(){
List<ObjectModel> list1=[
ObjectModel(date:"1",dayData:12),
ObjectModel(date:"2",dayData:15),
];
//here is the list 2
List<ObjectModel> list2=[
ObjectModel(date:"1",nightData:56),
ObjectModel(date:"3",nightData:80),
];
//expected output
List<ObjectModel> expectedList= [];
list1.forEach((element) {
ObjectModel innerObject = list2.firstWhere((ObjectModel innerElement) => element.date == innerElement.date, orElse: (){return ObjectModel();});
if(innerObject.date !=null){
expectedList.add(ObjectModel(date:element.date,dayData:element.dayData,nightData: innerObject.nightData));
}else{
expectedList.add(element);
}
});
list2.forEach((element) {
ObjectModel innerObject = list1.firstWhere((ObjectModel innerElement) => element.date == innerElement.date, orElse: (){return ObjectModel();});
if(innerObject.date ==null){
expectedList.add(element);
}
});
print(expectedList.length);
}
class ObjectModel{
String? date;
int? dayData;
int? nightData;
ObjectModel({ this.date, this.dayData, this.nightData});
}

Uncorrectly modeling data from Json API response

Trying to fetch data from my API in Flutter. I am able to fetch data from the rest of the fields but not for "Behavior" field.
Here's my json:
[
{
"_id": {
"$oid": "625f2900fe6aeb351381c3f5"
},
"breed": "Africanis",
"origin": "Southern Africa",
"url": "https://en.wikipedia.org/wiki/Africanis",
"img": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Africanis_%281%29.jpg/220px-Africanis_%281%29.jpg",
"WikiDescr": [
{
"contenido": "some content"
}
],
"Behavior": [
{
"good_with_children": 3,
"good_with_other_dogs": 1,
"shedding": 3,
"grooming": 3,
"drooling": 1,
"coat_length": 1,
"good_with_strangers": 2,
"playfulness": 3,
"protectiveness": 5,
"trainability": 3,
"energy": 4,
"barking": 2,
"min_life_expectancy": 10,
"max_life_expectancy": 14,
"max_height_male": 28,
"max_height_female": 28,
"max_weight_male": 130,
"max_weight_female": 100,
"min_height_male": 26,
"min_height_female": 26,
"min_weight_male": 100,
"min_weight_female": 70
}
],
"url_alternative": []
}
]
And here's my dart model generated from https://app.quicktype.io/ :
class DogClass {
Id? _iId;
String? _breed;
String? _origin;
String? _url;
String? _img;
List<WikiDescr>? _wikiDescr;
List<Behavior>? _behavior;
List<dynamic>? _urlAlternative;
DogClass({
Id? iId,
String? breed,
String? origin,
String? url,
String? img,
List<WikiDescr>? wikiDescr,
List<Behavior>? behavior,
List<dynamic>? urlAlternative
}) {
if (iId != null) {
this._iId = iId;
}
if (breed != null) {
this._breed = breed;
}
if (origin != null) {
this._origin = origin;
}
if (url != null) {
this._url = url;
}
if (img != null) {
this._img = img;
}
if (img != null) {
this._img = img;
}
if (wikiDescr != null) {
this._wikiDescr = wikiDescr;
}
if (behavior != null) {
this._behavior = behavior;
}
if (urlAlternative != null) {
this._urlAlternative = urlAlternative;
}
}
Id? get iId => _iId;
set iId(Id? iId) => _iId = iId;
String? get breed => _breed;
set breed(String? breed) => _breed = breed;
String? get origin => _origin;
set origin(String? origin) => _origin = origin;
String? get url => _url;
set url(String? url) => _url = url;
String? get img => _img;
set img(String? img) => _img = img;
List<WikiDescr>? get wikiDescr => _wikiDescr;
set wikiDescr(List<WikiDescr>? wikiDescr) => _wikiDescr = wikiDescr;
List<Behavior>? get behavior => _behavior;
set behavior(List<Behavior>? behavior) => _behavior = behavior;
List<dynamic>? get urlAlternative => _urlAlternative;
set urlAlternative(List<dynamic>? urlAlternative) => _urlAlternative = urlAlternative;
factory DogClass.fromJson(Map<String, dynamic> json) {
return DogClass(
iId: json['_id'] == null
? null
: Id.fromJson(json['_id'] as Map<String, dynamic>),
breed: json['breed'] as String?,
origin: json['origin'] as String?,
url: json['url'] as String?,
img: json['img'] as String?,
wikiDescr: List<WikiDescr>.from(
json["WikiDescr"].map((x) => WikiDescr.fromJson(x))),
behavior: List<Behavior>.from(json["Behavior"].map((x) => Behavior.fromJson(x))),
urlAlternative: List<UrlAlternative>.from(json["url_alternative"].map((x) => UrlAlternative.fromJson(x)))
);
}
}
class Id {
String? _oid;
Id({String? oid}) {
if (oid != null) {
this._oid = oid;
}
}
String? get oid => _oid;
set oid(String? oid) => _oid = oid;
Id.fromJson(Map<String, dynamic> json) {
_oid = json['$oid'];
}
}
class WikiDescr {
WikiDescr({
required this.contenido,
});
String contenido;
factory WikiDescr.fromRawJson(String str) =>
WikiDescr.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory WikiDescr.fromJson(Map<String, dynamic> json) => WikiDescr(
contenido: json["contenido"],
);
Map<String, dynamic> toJson() => {
"contenido": contenido,
};
}
class Behavior {
int? _goodWithChildren;
int? _goodWithOtherDogs;
int? _shedding;
int? _grooming;
int? _drooling;
int? _coatLength;
int? _goodWithStrangers;
int? _playfulness;
int? _protectiveness;
int? _trainability;
int? _energy;
int? _barking;
int? _minLifeExpectancy;
int? _maxLifeExpectancy;
int? _maxHeightMale;
int? _maxHeightFemale;
int? _maxWeightMale;
int? _maxWeightFemale;
int? _minHeightMale;
int? _minHeightFemale;
int? _minWeightMale;
int? _minWeightFemale;
Behavior(
{int? goodWithChildren,
int? goodWithOtherDogs,
int? shedding,
int? grooming,
int? drooling,
int? coatLength,
int? goodWithStrangers,
int? playfulness,
int? protectiveness,
int? trainability,
int? energy,
int? barking,
int? minLifeExpectancy,
int? maxLifeExpectancy,
int? maxHeightMale,
int? maxHeightFemale,
int? maxWeightMale,
int? maxWeightFemale,
int? minHeightMale,
int? minHeightFemale,
int? minWeightMale,
int? minWeightFemale}) {
if (goodWithChildren != null) {
this._goodWithChildren = goodWithChildren;
}
if (goodWithOtherDogs != null) {
this._goodWithOtherDogs = goodWithOtherDogs;
}
if (shedding != null) {
this._shedding = shedding;
}
if (grooming != null) {
this._grooming = grooming;
}
if (drooling != null) {
this._drooling = drooling;
}
if (coatLength != null) {
this._coatLength = coatLength;
}
if (goodWithStrangers != null) {
this._goodWithStrangers = goodWithStrangers;
}
if (playfulness != null) {
this._playfulness = playfulness;
}
if (protectiveness != null) {
this._protectiveness = protectiveness;
}
if (trainability != null) {
this._trainability = trainability;
}
if (energy != null) {
this._energy = energy;
}
if (barking != null) {
this._barking = barking;
}
if (minLifeExpectancy != null) {
this._minLifeExpectancy = minLifeExpectancy;
}
if (maxLifeExpectancy != null) {
this._maxLifeExpectancy = maxLifeExpectancy;
}
if (maxHeightMale != null) {
this._maxHeightMale = maxHeightMale;
}
if (maxHeightFemale != null) {
this._maxHeightFemale = maxHeightFemale;
}
if (maxWeightMale != null) {
this._maxWeightMale = maxWeightMale;
}
if (maxWeightFemale != null) {
this._maxWeightFemale = maxWeightFemale;
}
if (minHeightMale != null) {
this._minHeightMale = minHeightMale;
}
if (minHeightFemale != null) {
this._minHeightFemale = minHeightFemale;
}
if (minWeightMale != null) {
this._minWeightMale = minWeightMale;
}
if (minWeightFemale != null) {
this._minWeightFemale = minWeightFemale;
}
}
int? get goodWithChildren => _goodWithChildren;
set goodWithChildren(int? goodWithChildren) =>
_goodWithChildren = goodWithChildren;
int? get goodWithOtherDogs => _goodWithOtherDogs;
set goodWithOtherDogs(int? goodWithOtherDogs) =>
_goodWithOtherDogs = goodWithOtherDogs;
int? get shedding => _shedding;
set shedding(int? shedding) => _shedding = shedding;
int? get grooming => _grooming;
set grooming(int? grooming) => _grooming = grooming;
int? get drooling => _drooling;
set drooling(int? drooling) => _drooling = drooling;
int? get coatLength => _coatLength;
set coatLength(int? coatLength) => _coatLength = coatLength;
int? get goodWithStrangers => _goodWithStrangers;
set goodWithStrangers(int? goodWithStrangers) =>
_goodWithStrangers = goodWithStrangers;
int? get playfulness => _playfulness;
set playfulness(int? playfulness) => _playfulness = playfulness;
int? get protectiveness => _protectiveness;
set protectiveness(int? protectiveness) => _protectiveness = protectiveness;
int? get trainability => _trainability;
set trainability(int? trainability) => _trainability = trainability;
int? get energy => _energy;
set energy(int? energy) => _energy = energy;
int? get barking => _barking;
set barking(int? barking) => _barking = barking;
int? get minLifeExpectancy => _minLifeExpectancy;
set minLifeExpectancy(int? minLifeExpectancy) =>
_minLifeExpectancy = minLifeExpectancy;
int? get maxLifeExpectancy => _maxLifeExpectancy;
set maxLifeExpectancy(int? maxLifeExpectancy) =>
_maxLifeExpectancy = maxLifeExpectancy;
int? get maxHeightMale => _maxHeightMale;
set maxHeightMale(int? maxHeightMale) => _maxHeightMale = maxHeightMale;
int? get maxHeightFemale => _maxHeightFemale;
set maxHeightFemale(int? maxHeightFemale) =>
_maxHeightFemale = maxHeightFemale;
int? get maxWeightMale => _maxWeightMale;
set maxWeightMale(int? maxWeightMale) => _maxWeightMale = maxWeightMale;
int? get maxWeightFemale => _maxWeightFemale;
set maxWeightFemale(int? maxWeightFemale) =>
_maxWeightFemale = maxWeightFemale;
int? get minHeightMale => _minHeightMale;
set minHeightMale(int? minHeightMale) => _minHeightMale = minHeightMale;
int? get minHeightFemale => _minHeightFemale;
set minHeightFemale(int? minHeightFemale) =>
_minHeightFemale = minHeightFemale;
int? get minWeightMale => _minWeightMale;
set minWeightMale(int? minWeightMale) => _minWeightMale = minWeightMale;
int? get minWeightFemale => _minWeightFemale;
set minWeightFemale(int? minWeightFemale) =>
_minWeightFemale = minWeightFemale;
factory Behavior.fromJson(Map<String, int> json) =>Behavior(
goodWithChildren : json['good_with_children'],
goodWithOtherDogs : json['good_with_other_dogs'],
shedding : json['shedding'],
grooming : json['grooming'],
drooling : json['drooling'],
coatLength : json['coat_length'],
goodWithStrangers : json['good_with_strangers'],
playfulness : json['playfulness'],
protectiveness : json['protectiveness'],
trainability : json['trainability'],
energy : json['energy'],
barking : json['barking'],
minLifeExpectancy : json['min_life_expectancy'],
maxLifeExpectancy : json['max_life_expectancy'],
maxHeightMale : json['max_height_male'],
maxHeightFemale : json['max_height_female'],
maxWeightMale : json['max_weight_male'],
maxWeightFemale : json['max_weight_female'],
minHeightMale : json['min_height_male'],
minHeightFemale : json['min_height_female'],
minWeightMale : json['min_weight_male'],
minWeightFemale : json['min_weight_female']
);
}
class UrlAlternative {
UrlAlternative({
required this.urls,
});
List<String> urls;
factory UrlAlternative.fromJson(Map<String, dynamic> json) => UrlAlternative(
urls: List<String>.from(json["urls"].map((x) => x)),
);
}
Please just focus on "behavior" field. The rest work correctly. Is there something I am missing in my factory method??
I prefer to create my own classes if needed only. I use generators when my data is very complex, your case is not.
You need to firstly deal with raw data then you can use classes and methods because you know how it is structured and how it can be handled to get certain info about it, IMHO.
import 'dart:convert';
import 'package:_samples4/json/json_africa_wiki.dart';
typedef JMap = Map<String, dynamic>;
void main(List<String> args) {
var list = (jsonDecode(rawJsonAfrica) as List).cast<JMap>();
var data = list.first;
var behaviour = (data['Behavior'] as List).first as JMap;
print(behaviour.keys);
print(behaviour.values);
}
Output:
(good_with_children, good_with_other_dogs, shedding, ..., min_weight_male, min_weight_female)
(3, 1, 3, 3, 1, 1, 2, 3, 5, 3, 4, 2, 10, 14, 28, 28, 130, 100, 26, 26, 100, 70)

dart null safety class initialization

I built two classes.
first class is the video Class.
second class is Player Class.
And one of Player variables is list of video class
and after dart null safety it is not allowed to add null varaiables
I should add initialization value to the class ( I don't want to add required ).
First Class - Video
import 'dart:convert';
VideoModel videoModelFromJson(String str) =>
VideoModel.fromJson(json.decode(str));
String videoModelToJson(VideoModel data) => json.encode(data.toJson());
class VideoModel {
VideoModel({
this.playerVideoId = -1,
this.playerIdId = -1,
this.videoLink = "Please Upload",
});
int playerVideoId;
int playerIdId;
String videoLink;
factory VideoModel.fromJson(Map<String, dynamic> json) => VideoModel(
playerVideoId: json["playerVideoId"],
playerIdId: json["playerId_id"],
videoLink: json["videoLink"],
);
Map<String, dynamic> toJson() => {
"playerVideoId": playerVideoId,
"playerId_id": playerIdId,
"videoLink": videoLink,
};
}
Second Class which contain error in defining videos
// To parse this JSON data, do
//
// final playerBasic = playerBasicFromJson(jsonString);
import 'dart:convert';
import 'package:sportive/pages/player/Model/Video_Model.dart';
PlayerBasic playerBasicFromJson(String str) =>
PlayerBasic.fromJson(json.decode(str));
String playerBasicToJson(PlayerBasic data) => json.encode(data.toJson());
class PlayerBasic {
PlayerBasic({
this.playerId = -1,
this.userIdId = -1,
this.playerFirstName = "",
this.playerLastName = "",
this.nationality = "",
this.birthday = "",
this.height = -1,
this.weight = -1,
this.currentCountry = "",
this.currentCity = "",
this.game = "",
this.image = "",
this.gender = "Male",
this.videos, // Error here Parameter The parameter 'videos' can't have a value of 'null' because of its type, but the implicit default value is 'null'.
//Try adding either an explicit non-'null' default value or the 'required' modifier
});
int playerId;
int userIdId;
String playerFirstName;
String playerLastName;
String nationality;
String birthday;
int height;
int weight;
String currentCountry;
String currentCity;
String game;
String image;
String gender;
List<VideoModel> videos;
factory PlayerBasic.fromJson(Map<String, dynamic> json) => PlayerBasic(
playerId: json["playerId"],
userIdId: json["userId_id"],
playerFirstName: json["playerFirstName"],
playerLastName: json["playerLastName"],
nationality: json["nationality"],
birthday: json["birthday"],
height: json["height"],
weight: json["weight"],
currentCountry: json["currentCountry"],
currentCity: json["currentCity"],
game: json["game"],
image: json["image"],
gender: json['gender'],
videos: json['videos'],
);
Map<String, dynamic> toJson() => {
"playerId": playerId,
"userId_id": userIdId,
"playerFirstName": playerFirstName,
"playerLastName": playerLastName,
"nationality": nationality,
"birthday": birthday,
"height": height,
"weight": weight,
"currentCountry": currentCountry,
"currentCity": currentCity,
"game": game,
"image": image,
"gender": gender,
"videos": videos,
};
}
Sorry Iam Flutter beginner question.
Just change the videos declaration to
List<VideoModel>? videos;
Let's suppose you have this class and you want to provide a default value for bar in the constructor:
class Foo {
List<int> bar;
}
If you want to be able to modify bar later:
class Foo {
// Use this
Foo({List<int>? bar}) : bar = bar ?? [];
List<int> bar;
}
void main() {
Foo foo;
foo = Foo();
print(foo.bar);
// Outputs []
foo.bar.add(4);
print(foo.bar);
// Outputs [4]
foo = Foo(bar: [1, 2, 3]);
print(foo.bar);
// Outputs [1, 2, 3]
foo.bar.add(4);
print(foo.bar);
// Outputs [1, 2, 3, 4]
}
If you want to keep bar immutable (i.e. you won't use methods such as add or remove):
class Foo {
// Use this
Foo({this.bar = const []});
List<int> bar;
}
void main() {
Foo foo;
foo = Foo();
print(foo.bar);
// Outputs []
// foo.bar.add(4);
// It'll throw Uncaught Error: Unsupported operation: add
foo = Foo(bar: [1, 2, 3]);
print(foo.bar);
// Outputs [1, 2, 3]
foo.bar.add(4);
print(foo.bar);
// Outputs [1, 2, 3, 4]
}

Remove duplicate from List<model> after merge

I want to add a list to my main List and remove duplicate, like this:
class item {
int id;
String title;
item({this.id, this.title});
}
void main() {
// this is working for List<int>
List<int> c = [1, 2, 3];
List<int> d = [3, 4, 5];
c.addAll(d..removeWhere((e) => c.contains(e)));
print(c);
// but this is not working for List<item>
List<item> a = new List<item>();
a.add(new item(id: 1, title: 'item1'));
a.add(new item(id: 2, title: 'item2'));
List<item> b = new List<item>();
b.add(new item(id: 2, title: 'item2'));
b.add(new item(id: 3, title: 'item3'));
a.addAll(b..removeWhere((e) => a.contains(e)));
a.forEach((f) => print('${f.id} ${f.title}'));
}
and output is like this:
[1, 2, 3, 4, 5]
1 item1
2 item2
2 item2
3 item3
As you test this code on https://dartpad.dev/ output is ok for List<int> but there is duplicate in output for List<item>.
The first list have integer values and when you call contains it will check the values and will work correctly.
In second case you have item objects. Both lists have objects that may have same property values but both are two different object. For example, the below code will work correctly in your case, because the item2 object is same in both lists.
Item item2 = Item(id: 2, title: 'item2');
List<Item> a = new List<Item>();
a.add(new Item(id: 1, title: 'item1'));
a.add(item2);
List<Item> b = new List<Item>();
b.add(item2);
b.add(new Item(id: 3, title: 'item3'));
When you call contains it will use the Object.== method, so to handle this issue you have to override that method and specify your own equality logic.
class Item {
int id;
String title;
Item({this.id, this.title});
#override
bool operator == (Object other) {
return
identical(this, other) ||
other is Item &&
runtimeType == other.runtimeType &&
id == other.id;
}
}
Or you can use the equatable package to handle it better.
References:
contains method
operator == method
I think you need to iterate on your list a if you want to compare a property (e.g title)
a.addAll(
b
..removeWhere((e) {
bool flag = false;
a.forEach((x) {
if (x.title.contains(e.title)) {
flag = true;
}
});
return flag;
}),
);
As suggested below, those two list items are different
Thats because these 2 item's:
a.add(new item(id: 2, title: 'item2'));
b.add(new item(id: 2, title: 'item2'));
are different. They are 2 instances of 2 different objects that just have the same values for id and title. As the documentation tells:
The default behavior for all Objects is to return true if and only if this and other are the same object.
If you want to compare if the 2 fields are the same you can override the equality operator inside your item class:
operator ==(item other) {
return (this.id == other.id && this.title == other.title);
}
which gives the expected output:
[1, 2, 3, 4, 5]
1 item1
2 item2
3 item3