Home > Mobile >  Filter List of Maps
Filter List of Maps

Time:02-03

Here a list of maps :

List values = [
  {'title': 'a', 'count': 1},
  {'title': 'b', 'count': 2},
  {'title': 'b', 'count': 8},
  {'title': 'c', 'count': 1},
  {'title': 'a', 'count': 4},
  {'title': 'a', 'count': 9},
]

I'm trying to create a new List of maps looks like this :

List myList = [
  {
    "title": "a",
    "values": [
      {
        {'title': 'a', 'count': 1},
        {'title': 'a', 'count': 4},
        {'title': 'a', 'count': 9},
      }
    ]
  },
  {
    "title": "b",
    "values": [
      {
        {'title': 'b', 'count': 2},
        {'title': 'b', 'count': 8}
      }
    ]
  },
  {
    "title": "a",
    "values": [
      {
        {'title': 'c', 'count': 1},
      }
    ]
  }
];

I found a solution using for loop. But is there any other solution to create list : myList?.

Edit :

Here my solution:

createList(List values) {
    List list = [];
    for (int i = 0; i < values.length; i  ) {
      if (list.any((element) => element['title'] == values[i]['title'])) {
        list
            .firstWhere((e) => e['title'] == values[i]['title'])['values']
            .add(values[i]);
      } else {
        list.add({
          'title': values[i]['title'],
          'values': [values[i]]
        });
      }
    }
    return list;
  }

CodePudding user response:

Here is one way, which starts with unique titles.

final result = values
    .map((v) => v['title'])
    .toSet()
    .map((title) => {
          'title': title,
          'values': values.where((v) => v['title'] == title).toList()
        })
    .toList();
print(result);

Another one with groupBy:

final result = groupBy(values, (v) => v['title'])
  .entries
  .map((g) => {'title': g.key, 'values': g.value})
  .toList();
print(result);

CodePudding user response:

I want to preface my answer by saying I am not very experienced with Dart, so please pardon any syntax errors. Perhaps someone can come in and fix them for me.

This is a code complexity problem. Unfortunately there is no way to remove loops entirely, as you obviously have to iterate over each value at least once to get the value. Therefore, the best solution will have a Big O notation of O(n).

However, in the code you posted, you're using firstWhere and any within your for loop, which are both going to have a worst-case complexity of O(n). When added together with your for loop, your method has a complexity of O(n^2), which is generally not ideal.

Your algorithm can be optimized by squishing this down into a single for loop with O(n) complexity. Here is how I would likely go about implementing something like this.



/// values is expected to be of the form:
/// [
///   {'title': 'a', 'count': 1},
///   {'title': 'b', 'count': 2},
///   {'title': 'b', 'count': 8},
///   {'title': 'c', 'count': 1},
///   {'title': 'a', 'count': 4},
///   {'title': 'a', 'count': 9},
/// ]
createList(List values) {

    Map valueMap = {};
    // Start by converting your list into a map where the keys are the title and the value is an array of your original entries
    for(int i = 0; i < values.length; i  ) {
        // If this "title" entry doesn't exist yet, make a list for it.
        if(valueMap[values[i]["title"]] is! List) {
            valueMap[values[i]["title"]] = [];
        }
        // Add the value to that list
        valueMap[values[i]["title"]].add(values[i]);
    }
  
    // valueMap should now have a structure like:
    // {
    //  "a": [{"title": "a", "count": 1}, {"title": "a", "count": 4}, {"title": "a", "count": 9}],
    //  "b": [{"title": "b", "count": 2}, {"title": "b", "count": 8}],
    //  "c": [{"title": "c", "count": 1}]
    // }

    // Now convert your map back into a List
    List newValueList = [];
    valueMap.forEach((key, value) => {
        newValueList.add({
            "title": key,
            "values": value
        })
    });
  
    // newValueList should now have a structure like:
    // [
    //   {
    //     "title": "a",
    //     "values": [{"title": "a", "count": 1}, {"title": "a", "count": 4}, {"title": "a", "count": 9}]
    //   },
    //   {
    //     "title": "b",
    //     "values": [{"title": "b", "count": 2}, {"title": "b", "count": 8}]
    //   },
    //   {
    //     "title": "c",
    //     "values": [{"title": "c", "count": 1}]
    //   }
    // ]
  
    return newValueList;
  }

This code does not include any nested for loops, and as such, it is an O(n) complexity function.

(Technically, there are two for loops, so you may think that the complexity is actually O(2n). Constants are typically stripped from big-o notation as their impact on the performance is negligible and does not change based on the size of the data set).

  • Related