Home > Software engineering >  Flutter/Dart- Filter nested list
Flutter/Dart- Filter nested list

Time:03-04

I want to filter out a list in Flutter/dart which has nested objects. I want to filter out the list based on the name property both with in the parent object and the child object subNames.

Below is the code that I have come up with, which gives me duplicates, is there a better way to solve this?

    var rawData = [{
            "name": "Testing 123",
            "subNames": [{
                "name": "Subtesting 123"
            }]
        },
        {
            "name": "Testing 456",
            "subNames": [{
                "name": "Subtesting 456"
            }]
        },
        {
            "name": "Testing 456",
            "subNames": []
        }
    ]
        
     final results = [
                ...rawData
                    .where((m) =>
                        m.name.toLowerCase().contains('subtesting 123'))// or Testing 123
                    .toList(),
                ...rawData
                    .where((m) => m.subNames
                        .where((s) =>
                            s.name.toLowerCase().contains('subtesting 123')) // or Testing 123
                        .isNotEmpty)
                    .toList()
              ];

Expected output:
//Results
[{
        "name": "Testing 123",
        "subNames": [{
            "name": "Subtesting 123"
        }]
    }, 
]

CodePudding user response:

First of all, it's better to use Class models and typed variables over json or dynamic nested types. Using this approach we can implement our logic easier. Here is a sample:

const rawData = [
  {
    "name": "Testing 123",
    "subNames": [
      {"name": "Subtesting 123"}
    ]
  },
  {
    "name": "Testing 456",
    "subNames": [
      {"name": "Subtesting 456"}
    ]
  },
  {"name": "Testing 456", "subNames": []}
];

class Model {
  String name;
  List<SubNames> subNames;

  Model({this.name, this.subNames});

  Model.fromJson(Map<String, dynamic> json) {
    name = json['name'];
    if (json['subNames'] != null) {
      subNames = <SubNames>[];
      json['subNames'].forEach((v) {
        subNames.add(new SubNames.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['name'] = this.name;
    if (this.subNames != null) {
      data['subNames'] = this.subNames.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class SubNames {
  String name;

  SubNames({this.name});

  SubNames.fromJson(Map<String, dynamic> json) {
    name = json['name'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['name'] = this.name;
    return data;
  }
}

void main() {
  List<Model> testModelList = rawData.map((e) => Model.fromJson(e)).toList();
  final result = testModelList.where((element) =>
      element.name.toLowerCase().contains('subtesting 123') ||
      element.subNames
          .any((sub) => sub.name.toLowerCase().contains('subtesting 123')));
  print('result.length : ${result.length}');
  result.forEach((element) {
    print(element.toJson());
  });
}

You can run this sample see the result.

CodePudding user response:

Try changing your results to the following

final results = [
  ...rawData
      .where((m) =>
          m.name.toLowerCase().contains('subtesting 123') 
            || m.subNames
          .where((s) =>
              s.name.toLowerCase().contains('subtesting 123')).toList().isNotEmpty)
      .toList(),
];

I'm assuming here you are parsing your rawData so you are able to use m.names instead of m['names']

  • Related