'Flutter Sort array by other array values
I have data like this
[{"name": "swimming"},{"name": "Politics"},{"name": "Gamer"}]
and I have profiles like
[
{
"username":"abc",
"passions":[
{
"name":"Snooker"
}
]
},
{
"username":"abc",
"passions":[
{
"name":"Coding"
}
]
},
{
"username":"xyz",
"passions":[
{
"name":"swimming"
}
]
},
{
"username":"abc",
"passions":[
{
"name":"Politics"
},
{
"name":"swimming"
}
]
}
]
What I need to do is show first those profiles whose passions are matching with that first data array and then the other rest remaining will show.
Solution 1:[1]
I'm sure there are better ways to do this, but this works.
final passions = [{"name": "swimming"},{"name": "Politics"},{"name": "Gamer"}];
final users =
[
{
"username":"abc",
"passions":[
{
"name":"Snooker"
}
]
},
{
"username":"efg",
"passions":[
{
"name":"Coding"
}
]
},
{
"username":"hij",
"passions":[
{
"name":"swimming"
}
]
},
{
"username":"klm",
"passions":[
{
"name":"Politics"
},
{
"name":"swimming"
}
]
}
];
var matches = [];
users.forEach((u) {
passions.forEach((p) {
if (p['name'] == (u['passions'] as List)[0]['name']) {
matches.add(u['username']);
}
});
});
print(matches.toString());
Solution 2:[2]
Just give this function a profile list and Finally returns the sort list
List passions = [{"name": "swimming"}, {"name": "Politics"}, {"name": "Gamer"} ];
List sortListPrfile(List profiles) {
//profiles is a list of result server
List _items = []; // It will be returned eventually
List _noItemCommon = []; //Items that are not common
for (var profile in profiles) {
for (var passion in passions) {
if (profile["passions"][0]["name"] == passion['name']) {
_items.add(profile);
} else {
_noItemCommon.add(profile);
}
}
}
_items.addAll(_noItemCommon);
return _items;
}
Solution 3:[3]
Here is a function that returns the complete list by matches first and by sorted users. Your code has a nested list object that needs to check for values that way is function has one line more :)
Note: This function is only for your current item which matches object keys. To make it more secure you should add guards.
import 'package:flutter/foundation.dart';
void main() {
final filtered = filteredByMatchesFirst(arr, matches);
for (var value in filtered) {
print(value);
}
}
var matches = <Map<String, dynamic>>[
{"name": "swimming"},
{"name": "Politics"},
{"name": "Gamer"},
];
var arr = <Map<String, dynamic>>[
{
"username": "abc",
"passions": [
{"name": "Snooker"}
]
},
{
"username": "abc",
"passions": [
{"name": "Coding"}
]
},
{
"username": "xyz",
"passions": [
{"name": "swimming"}
]
},
{
"username": "byz",
"passions": [
{"name": "Gamer"}
]
},
{
"username": "abc",
"passions": [
{"name": "Politics"},
{"name": "swimming"}
]
}
];
List<Map<String, dynamic>> filteredByMatchesFirst(
List<Map<String, dynamic>> list,
List<Map<String, dynamic>> matches,
) {
// Sort list by users first.
list.sort((m1, m2) {
return (m1['username'] as String).compareTo(m2['username'] as String);
});
// Filter only match values.
var filtered = list.where((map) {
final passions = map['passions'] as List<Map<String, dynamic>>;
return passions.any((a) => matches.any((b) => mapEquals(a, b)));
}).toList();
// Add the rest to the filtered list without duplicates.
return filtered.followedBy(list).toSet().toList();
}
Output:
{username: abc, passions: [{name: Politics}, {name: swimming}]}
{username: byz, passions: [{name: Gamer}]}
{username: xyz, passions: [{name: swimming}]}
{username: abc, passions: [{name: Snooker}]}
{username: abc, passions: [{name: Coding}]}
Output without matching:
{username: abc, passions: [{name: Snooker}]}
{username: abc, passions: [{name: Coding}]}
{username: abc, passions: [{name: Politics}, {name: swimming}]}
{username: byz, passions: [{name: Gamer}]}
{username: xyz, passions: [{name: swimming}]}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | jbmcle |
| Solution 2 | behnam bagvand |
| Solution 3 |
