flutterdartdart-editordart-2dartdoc

From given two lists, how to extract all the elements from one list that are not available in the other list in Dart?


I have two lists in Dart as below,

  final List availableIssueComponents = [
    {'id': 1, 'componentName': 'Cash Acceptor'},
    {'id': 2, 'componentName': 'Printer'},
    {'id': 3, 'componentName': 'PIN Pad'},
    {'id': 4, 'componentName': 'Key Board'},
    {'id': 5, 'componentName': 'Touch Screen'},
    {'id': 6, 'componentName': 'Computer'},
    {'id': 7, 'componentName': 'Application'},
    {'id': 8, 'componentName': 'Network'},
    {'id': 9, 'componentName': 'Power'},
    {'id': 10, 'componentName': 'Camera'},
    {'id': 11, 'componentName': 'Safe'},
    {'id': 13, 'componentName': 'Screen'},
    {'id': 14, 'componentName': 'Battery'},
    {'id': 15, 'componentName': 'Ports'},
    {'id': 16, 'componentName': 'Application'},
    {'id': 17, 'componentName': 'Safe'},
    {'id': 18, 'componentName': 'Camera'},
    {'id': 19, 'componentName': 'Power'},
    {'id': 20, 'componentName': 'Key Board'},
    {'id': 21, 'componentName': 'PIN Pad'},
    {'id': 22, 'componentName': 'Printer'},
    {'id': 23, 'componentName': 'Computer'},
    {'id': 24, 'componentName': 'Touch Screen'},
    {'id': 25, 'componentName': 'Application'},
    {'id': 26, 'componentName': 'Network'}
  ];

  final List selectedIssueComponents = [
    {'id': 3, 'componentName': 'PIN Pad'},
    {'id': 6, 'componentName': 'Computer'},
    {'id': 19, 'componentName': 'Power'},
  ];

From the above two lists, I am trying to select all the elements from the availableIssueComponents excluding the elements that are already available in the selectedIssueComponents.

Ex: Since components with ids of 3, 6, 19 are common in both the lists, I would want a third list that contains all the components excluding the components with the ids of 3, 6, 19.

The third list should look like below,

  final List availableIssueComponents = [
    {'id': 1, 'componentName': 'Cash Acceptor'},
    {'id': 2, 'componentName': 'Printer'},
    {'id': 4, 'componentName': 'Key Board'},
    {'id': 5, 'componentName': 'Touch Screen'},
    {'id': 7, 'componentName': 'Application'},
    {'id': 8, 'componentName': 'Network'},
    {'id': 9, 'componentName': 'Power'},
    {'id': 10, 'componentName': 'Camera'},
    {'id': 11, 'componentName': 'Safe'},
    {'id': 13, 'componentName': 'Screen'},
    {'id': 14, 'componentName': 'Battery'},
    {'id': 15, 'componentName': 'Ports'},
    {'id': 16, 'componentName': 'Application'},
    {'id': 17, 'componentName': 'Safe'},
    {'id': 18, 'componentName': 'Camera'},
    {'id': 20, 'componentName': 'Key Board'},
    {'id': 21, 'componentName': 'PIN Pad'},
    {'id': 22, 'componentName': 'Printer'},
    {'id': 23, 'componentName': 'Computer'},
    {'id': 24, 'componentName': 'Touch Screen'},
    {'id': 25, 'componentName': 'Application'},
    {'id': 26, 'componentName': 'Network'}
  ];

I tried to do this using Sets and the following was my approach,

Set availableComponentsSet = Set.from(availableIssueComponents);
Set issueComponentsSet = Set.from(selectedIssueComponents);

Set resultComponents = availableComponentsSet.difference(issueComponentsSet);

But when logged to the console it resultComponents contained all the components. Which is not what I wanted. I also tried nested for loops and it did not work either.


Solution

  • The components objects are not filtered by the Set when using a Set<Map> because Map is a reference type and is considered unique unless the two objects being compared are pointing at the same instance (as @Pat9RB commented).

    I would map the selected IDs to a list, then filter out those IDs using List#where(fn)

    final availableIssueComponents = [
      {'id': 1, 'componentName': 'Cash Acceptor'},
      {'id': 2, 'componentName': 'Printer'},
      {'id': 3, 'componentName': 'PIN Pad'},
      {'id': 4, 'componentName': 'Key Board'},
      {'id': 5, 'componentName': 'Touch Screen'},
      {'id': 6, 'componentName': 'Computer'},
      {'id': 7, 'componentName': 'Application'},
      {'id': 8, 'componentName': 'Network'},
      {'id': 9, 'componentName': 'Power'},
      {'id': 10, 'componentName': 'Camera'},
      {'id': 11, 'componentName': 'Safe'},
      {'id': 13, 'componentName': 'Screen'},
      {'id': 14, 'componentName': 'Battery'},
      {'id': 15, 'componentName': 'Ports'},
      {'id': 16, 'componentName': 'Application'},
      {'id': 17, 'componentName': 'Safe'},
      {'id': 18, 'componentName': 'Camera'},
      {'id': 19, 'componentName': 'Power'},
      {'id': 20, 'componentName': 'Key Board'},
      {'id': 21, 'componentName': 'PIN Pad'},
      {'id': 22, 'componentName': 'Printer'},
      {'id': 23, 'componentName': 'Computer'},
      {'id': 24, 'componentName': 'Touch Screen'},
      {'id': 25, 'componentName': 'Application'},
      {'id': 26, 'componentName': 'Network'}
    ];
    
    final selectedIssueComponents = [
      {'id': 3, 'componentName': 'PIN Pad'},
      {'id': 6, 'componentName': 'Computer'},
      {'id': 19, 'componentName': 'Power'},
    ];
    
    final selectedIds = selectedIssueComponents.map((component) => component['id']).toList();
    final filtered = availableIssueComponents.where((element) => !selectedIds.contains(element["id"])).toList();
    
    print(filtered);
    

    If you prefer to use Set and difference you could create sets of the ids. This would create a set of int (Set<int>) which is a primative type and would allow the type of filtering expected:

    final availableIssueComponents = [
      {'id': 1, 'componentName': 'Cash Acceptor'},
      {'id': 2, 'componentName': 'Printer'},
      {'id': 3, 'componentName': 'PIN Pad'},
      {'id': 4, 'componentName': 'Key Board'},
      {'id': 5, 'componentName': 'Touch Screen'},
      {'id': 6, 'componentName': 'Computer'},
      {'id': 7, 'componentName': 'Application'},
      {'id': 8, 'componentName': 'Network'},
      {'id': 9, 'componentName': 'Power'},
      {'id': 10, 'componentName': 'Camera'},
      {'id': 11, 'componentName': 'Safe'},
      {'id': 13, 'componentName': 'Screen'},
      {'id': 14, 'componentName': 'Battery'},
      {'id': 15, 'componentName': 'Ports'},
      {'id': 16, 'componentName': 'Application'},
      {'id': 17, 'componentName': 'Safe'},
      {'id': 18, 'componentName': 'Camera'},
      {'id': 19, 'componentName': 'Power'},
      {'id': 20, 'componentName': 'Key Board'},
      {'id': 21, 'componentName': 'PIN Pad'},
      {'id': 22, 'componentName': 'Printer'},
      {'id': 23, 'componentName': 'Computer'},
      {'id': 24, 'componentName': 'Touch Screen'},
      {'id': 25, 'componentName': 'Application'},
      {'id': 26, 'componentName': 'Network'}
    ];
    
    final selectedIssueComponents = [
      {'id': 3, 'componentName': 'PIN Pad'},
      {'id': 6, 'componentName': 'Computer'},
      {'id': 19, 'componentName': 'Power'},
    ];
    final availableIds = availableIssueComponents.map((component) => component['id']).toSet();
    final selectedIds = selectedIssueComponents.map((component) => component['id']).toSet();
    final filteredIds = availableIds.difference(selectedIds);
    final filteredComponents = availableIssueComponents.where((element) => filteredIds.contains(element["id"])).toList();
    
    print(filteredComponents);