Home > database >  Dart: How to Merge array based on ID?
Dart: How to Merge array based on ID?

Time:02-26

I have an complex list but I need to merge them plz help me..

    var itemlist1=[
      {"p_id": "a101", "p_name": "item1","type": "finished"},
      {"p_id": "a102", "p_name": "item2","type": "s-finished"},
      {"p_id": "b101", "p_name": "item3","type": "finished"},
      {"p_id": "c105", "p_name": "item4","type": "finished"}];

var itemlist2=[
      {"p_id": "a101", "type": "finished", "quantity": 605, "price": 1200},
      {"p_id": "a102", "type": "semi finished", "quantity": 150, "price": 950},     
      {"p_id": "c105", "type": "finished", "quantity": 560, "price":665}];

i need list like below.

var itemlist3=[
{"p_id": "a101", "p_name": "item1", "type": "finished", "quantity": 605, "price": 1200},
{"p_id": "a102", "p_name": "item2", "type": "s-finished", "quantity": 150, "price": 950},    
{"p_id": "b101", "p_name": "item3", "type": "finished", "quantity": 0, "price": 0},      
{"p_id": "c105", "p_name": "item4", "type": "finished", "quantity": 560, "price":665}];

how to achive this ? help me..

CodePudding user response:

Ok so your result list takes the p_id, p_name and type from the first list, like this:

List<Map<String, dynamic>> result = itemList1.map((item) {
  var resultItem = Map.from(item);
  return resultItem;
});

However you also want to add quantity and price from the second list, like this:

List<Map<String, dynamic>> result = itemList1.map((item) {
  var resultItem = Map.from(item);
  var list2Obj = itemList2.firstWhereOrNull((value) => value['p_id'] == item['p_id']);
  var quantity = list2Obj != null ? list2Obj['quantity'] : 0;
  var price = list2Obj != null ? list2Obj['price'] : 0;

  resultItem['quantity'] = quantity;
  resultItem['price'] = price;

  return resultItem;
});

I used the firstWhereOrNull function from the package:collection module. If you don't want to use it, here is a simple implementation:

T? firstWhereOrNull<T>(List<T> list, bool Function(T) fun) {
  try {
    return list.FirstWhere(fun);
  } on StateError {
    return null;
  }
}

I can't test the implementation right now, but it should work

CodePudding user response:

You can achive it by looping one of the list and getting its corresponding value from the other list. Then merge them.

var itemlist1 = [
      {"p_id": "a101", "p_name": "item1","type": "finished"},
      {"p_id": "a102", "p_name": "item2","type": "s-finished"},
      {"p_id": "b101", "p_name": "item3","type": "finished"},
      {"p_id": "c105", "p_name": "item4","type": "finished"}];

    var itemlist2 = [
      {"p_id": "a101", "type": "finished", "quantity": 605, "price": 1200},
      {"p_id": "a102", "type": "semi finished", "quantity": 150, "price": 950},     
      {"p_id": "c105", "type": "finished", "quantity": 560, "price":665}];
  
    var itemlist3 = itemlist2.map((map){
      var _matches = itemlist1.where((val)=> val['p_id'] == map['p_id']);
      if(_matches.isNotEmpty){
        return {..._matches.first, ...map};
      }
    }).toList();

CodePudding user response:

You want to merge two List<Map>s such that Maps that have the same p_id value are combined. To make it easy and fast to find an existing Map from a p_id value, it'd help to first create a Map<String, Map> to use as a lookup table to map p_id values to Maps. As we iterate over the Lists, we'll merge each Map with an existing entry in the table. Two Maps can be easily merged with the spread operator.

Once that's done, we can create a List<Map> from the values of the table.

For example:

var itemlist1 = <Map<String, dynamic>>[
  {"p_id": "a101", "p_name": "item1", "type": "finished"},
  {"p_id": "a102", "p_name": "item2", "type": "s-finished"},
  {"p_id": "b101", "p_name": "item3", "type": "finished"},
  {"p_id": "c105", "p_name": "item4", "type": "finished"}
];

var itemlist2 = <Map<String, dynamic>>[
  {"p_id": "a101", "type": "finished", "quantity": 605, "price": 1200},
  {"p_id": "a102", "type": "semi finished", "quantity": 150, "price": 950},
  {"p_id": "c105", "type": "finished", "quantity": 560, "price": 665}
];

void main() {
  var mergedMap = <String, Map<String, dynamic>>{};

  // Instead of `itemlist1   itemlist2`, alternatively use CombinedIterableView
  // from package:collection to avoid allocating a new `List`.
  for (var map in itemlist1   itemlist2) {
    var id = map['p_id']!;
    var existingEntry = mergedMap[id] ?? {};
    mergedMap[id] = {...existingEntry, ...map};
  }

  var itemlist3 = mergedMap.values.toList();
  
  print(itemlist3);
}

Presuming that there's a constant number of entries for each Map, this approach should be O(m n) where m and n are the sizes of the two List<Map>s to merge.

  • Related