How to properly sort list by another list in Dart - flutter

I have two lists, 1 is a list of Map items, and another list which is the order.
I would like to sort the items based on their description attribute and compare them with the order list and have them inserted at the top.
import 'package:collection/collection.dart';
void main() {
List<String> order = [
'top european',
'top usa',
'top rest of the world'
];
List<Map> items = [
{'id': 0, 'id2': 5, 'description': 'Top USA'},
{'id': 2, 'id2': 2, 'description': 'Top A'},
{'id': 3, 'id2': 0, 'description': 'Top Z'},
{'id': 6, 'id2': 6, 'description': 'Top Rest of the world'},
{'id': 4, 'id2': 4, 'description': 'Top C'},
{'id': 5, 'id2': 1, 'description': 'Top D'},
{'id': 1, 'id2': 3, 'description': 'Top European'},
];
//this works but adds the items at the end
items.sort((a,b) {
return order.indexOf(a['description'].toLowerCase()) -
order.indexOf(b['description'].toLowerCase());
});
///Results: print(items);
// List<Map> items = [
// {'id': 2, 'id2': 2, 'description': 'Top A'},
// {'id': 3, 'id2': 0, 'description': 'Top Z'},
// {'id': 4, 'id2': 4, 'description': 'Top C'},
// {'id': 5, 'id2': 1, 'description': 'Top D'},
// {'id': 1, 'id2': 3, 'description': 'Top European'},
// {'id': 0, 'id2': 5, 'description': 'Top USA'},
// {'id': 6, 'id2': 6, 'description': 'Top Rest of the world'},
// ];
}
SOLUTION: I also tried this approach which is not ideal, but it works.
List <Map> itemsOrder = items
.where(
(ele) => order.contains(ele['description'].toString().toLowerCase()))
.toList();
itemsOrder.sort((a, b) {
return order.indexOf(a['description'].toLowerCase()) -
order.indexOf(b['description'].toLowerCase());
});
items.removeWhere(
(ele) => order.contains(ele['description'].toString().toLowerCase()));
itemsOrder = itemsOrder.reversed.toList();
for (int i = 0; i < itemsOrder.length; i++) {
items.insert(0, itemsOrder[i]);
}
///Results: print(items);
// List<Map> items = [
// {'id': 1, 'id2': 3, 'description': 'Top European'},
// {'id': 0, 'id2': 5, 'description': 'Top USA'},
// {'id': 6, 'id2': 6, 'description': 'Top Rest of the world'},
// {'id': 2, 'id2': 2, 'description': 'Top A'},
// {'id': 3, 'id2': 0, 'description': 'Top Z'},
// {'id': 4, 'id2': 4, 'description': 'Top C'},
// {'id': 5, 'id2': 1, 'description': 'Top D'},
// ];
Ideally, I would like to use sortBy or sortByCompare but unfortunately, I cannot find a proper example or get a grasp of how to use it.

The way I would fix this is to find the index of the description in the order list and if it cannot be found, I would use a number that is out of index inside the order list to indicate that this item should be at the bottom of the list.
This would be my solution:
void testIt() {
final outOfBounds = order.length + 1;
const description = 'description';
items.sort(
(lhs, rhs) {
final lhsDesc = (lhs[description] as String).toLowerCase();
final rhsDesc = (rhs[description] as String).toLowerCase();
final lhsIndex =
order.contains(lhsDesc) ? order.indexOf(lhsDesc) : outOfBounds;
final rhsIndex =
order.contains(rhsDesc) ? order.indexOf(rhsDesc) : outOfBounds;
return lhsIndex.compareTo(rhsIndex);
},
);
}
And the result is:
[{id: 1, id2: 3, description: Top European}, {id: 0, id2: 5, description: Top USA}, {id: 6, id2: 6, description: Top Rest of the world}, {id: 2, id2: 2, description: Top A}, {id: 3, id2: 0, description: Top Z}, {id: 4, id2: 4, description: Top C}, {id: 5, id2: 1, description: Top D}]

Related

Dynamically Calculate Time using Loops in Dart

I need to create 96 Map objects in a List with the following key-value pairs
{
'id': 1,
'time': '00:00-00:15',
'slotNumber': '01',
'clicked': false
}
Although this is something that is easily achievable using loops, the main complication starts when it comes to generating the time range. The time key in every object needs to be at an interval of 15 minutes each and should be in a 24-hour format. For example, the next few time ranges need to be 00:15-00:30, 00:30-00:45, 00:45-01:00, and so on. I tried hard to look for a package that would answer all my prayers but couldn't find any.
The final output needs to look something like this:
var kSlots = [
{'id': 1, 'time': '00:00-00:15', 'slotNumber': '01', 'clicked': false},
{'id': 2, 'time': '00:15-00:30', 'slotNumber': '02', 'clicked': false},
{'id': 3, 'time': '00:45-01:00', 'slotNumber': '03', 'clicked': false},
{'id': 4, 'time': '01:00-01:15', 'slotNumber': '04', 'clicked': false},
{'id': 5, 'time': '01:15-01:30', 'slotNumber': '05', 'clicked': false},
{'id': 6, 'time': '01:30-01:45', 'slotNumber': '06', 'clicked': false},
{'id': 7, 'time': '01:45-02:00', 'slotNumber': '07', 'clicked': false},
{'id': 8, 'time': '02:00-02:15', 'slotNumber': '08', 'clicked': false}]
As I now need to generate the time from a given start date which is in String, I tried modifying #jamesdlin 's answer a bit to achieve that. But it throws the following error:
Uncaught Error: FormatException: Invalid date format
08:00
String getTimeRange(int i) {
var midnight = DateTime.parse(DateFormat('HH:mm').format(DateTime.parse('08:00')));
const interval = Duration(minutes: 15);
var start = midnight.add(interval * i);
var end = start.add(interval);
var formatTime = DateFormat('HH:mm').format;
return '${formatTime(start)}-${formatTime(end)}';
}
void main() {
var slots = [
for (var i = 0; i < 20; i += 1)
<String, dynamic>{
'id': i + 1,
'time': getTimeRange(i),
'slotNumber': '${i + 1}'.padLeft(2, '0'),
'clicked': false,
},
];
slots.forEach(print);
}
Loop over an index and use the index as a multiplier for a Duration of 15 minutes.
You then either can add that multiplied Duration to a DateTime representing midnight (if your time ranges represent points in time) or format those Durations directly (if they represent durations).
I assuming that your times represent points in time:
import 'package:intl/intl.dart';
String getTimeRange(int i) {
var midnight = DateTime.utc(2022, 1, 1);
const interval = Duration(minutes: 15);
var start = midnight.add(interval * i);
var end = start.add(interval);
var formatTime = DateFormat('HH:mm').format;
return '${formatTime(start)}-${formatTime(end)}';
}
void main() {
var slots = [
for (var i = 0; i < 8; i += 1)
<String, dynamic>{
'id': i + 1,
'time': getTimeRange(i),
'slotNumber': '${i + 1}'.padLeft(2, '0'),
'clicked': false,
},
];
slots.forEach(print);
}
You can set use the DateTime class instead of String and manipulate it as you desire: https://api.flutter.dev/flutter/dart-core/DateTime-class.html

Flutter remove duplicate array by value

I have an array that has the same name value I just need to check if the same value comes it will delete it.
My data looks like
[{'name':'Rameez', 'data': [{'age': 1, 'number': 2}]}, {'name':'XYZ', 'data': [{'age': 1, 'number': 2}]}, {'name':'Rameez', 'data': [{'age': 1, 'number': 2}]}];
I want to show it like this no duplicate name
Expected output dataaa = [{'name':'Rameez', 'data': [{'age': 1, 'number': 2}]}, {'name':'XYZ', 'data': [{'age': 1, 'number': 2}]}];
var list = [{'name':'Rameez', 'data': [{'age': 1, 'number': 2}]},
{'name':'XYZ', 'data': [{'age': 1, 'number': 2}]},
{'name':'Rameez', 'data': [{'age': 1, 'number': 2}]}];
for(int i = 0;i< list.length;i++){
for(int j = i+1;j< list.length;j++){
if(list[i]["name"] == list[j]["name"]){
list.removeAt(j);
}
}
}
list.forEach((item) => print(item.toString()));
Output
{name: Rameez, data: [{age: 1, number: 2}]}
{name: XYZ, data: [{age: 1, number: 2}]}

Dart // Flutter: How to remove Items from List depending on content of entry

In my Flutter app, I have a database which keeps track of which items the user liked and which he disliked. I have the function
List finalFavoritesList;
void queryDb() async {
final db = await database;
final allRows = await db.query(TABLE_FAVORITE);
List finalFavoritesList = allRows.toList(growable: true);
print(finalFavoritesList);
}
which in my understanding creates a dart list from the sqflite database. Logcat prints:
[{id: 0, isFavorite: 0}, {id: 1, isFavorite: 1}, {id: 2, isFavorite: 0}, {id: 3, isFavorite: 1}, {id: 4, isFavorite: 0}, {id: 5, isFavorite: 1}]
Now I want to remove every entry, where isFavorite is equal to 0 but I don't know how. This new list should have another name.
I think your question itself has an answer!
Use removeWhere function.
List favorite = [{'id': 0, 'isFavorite': 0}, {'id': 1, 'isFavorite': 1}, {'id': 2, 'isFavorite': 0}, {'id': 3, 'isFavorite': 1}, {'id': 4, 'isFavorite': 0}, {'id': 5, 'isFavorite': 1}];
favorite.removeWhere((item) => item['isFavorite'] == 0);
print(favorite);
Output:
[{id: 1, isFavorite: 1}, {id: 3, isFavorite: 1}, {id: 5, isFavorite: 1}]
Refer: https://api.dart.dev/stable/2.9.3/dart-core/List/removeWhere.html
Hope that solves your case!

kafka-streams join produce duplicates

I have two topics:
// photos
{'id': 1, 'user_id': 1, 'url': 'url#1'},
{'id': 2, 'user_id': 2, 'url': 'url#2'},
{'id': 3, 'user_id': 2, 'url': 'url#3'}
// users
{'id': 1, 'name': 'user#1'},
{'id': 1, 'name': 'user#1'},
{'id': 1, 'name': 'user#1'}
I create map photo by user
KStream<Integer, Photo> photo_by_user = ...
photo_by_user.to("photo_by_user")
Then, I try to join two tables:
KTable<Integer, User> users_table = builder.table("users");
KTable<Integer, Photo> photo_by_user_table = builder.table("photo_by_user");
KStream<Integer, Result> results = users_table.join(photo_by_user_table, (a, b) -> Result.from(a, b)).toStream();
results.to("results");
result like
{'photo_id': 1, 'user': 1, 'url': 'url#1', 'name': 'user#1'}
{'photo_id': 2, 'user': 2, 'url': 'url#2', 'name': 'user#2'}
{'photo_id': 3, 'user': 3, 'url': 'url#3', 'name': 'user#3'}
{'photo_id': 1, 'user': 1, 'url': 'url#1', 'name': 'user#1'}
{'photo_id': 2, 'user': 2, 'url': 'url#2', 'name': 'user#2'}
{'photo_id': 3, 'user': 3, 'url': 'url#3', 'name': 'user#3'}
I see that results are duplicated. Why, and how to avoid it?
You might hit a known bug. On "flush" KTable-KTable join might produce some duplicates. Note, that those duplicates are strictly speaking not incorrect, because the result is an update-stream and updating "A" to "A" does not change the result. It's of course undesired to get those duplicates. Try to disable caching -- without caching, the "flush issues" should not occur.

Django/NetworkX Eliminating Repeated Nodes

I want to use d3js to visualize the connections between the users of my Django website.
I am reusing the code for the force directed graph example wich requires that each node has two attributes (ID and Name). I have created a node for each user in user_profiles_table and added an edge between already created nodes based on each row in connections_table. It does not work; networkx creates new nodes when I start working with the connection_table.
nodeindex=0
for user_profile in UserProfile.objects.all():
sourcetostring=user_profile.full_name3()
G.add_node(nodeindex, name=sourcetostring)
nodeindex = nodeindex +1
for user_connection in Connection.objects.all():
target_tostring=user_connection.target()
source_tostring=user_connection.source()
G.add_edge(sourcetostring, target_tostring, value=1)
data = json_graph.node_link_data(G)
result:
{'directed': False,
'graph': [],
'links': [{'source': 6, 'target': 7, 'value': 1},
{'source': 7, 'target': 8, 'value': 1},
{'source': 7, 'target': 9, 'value': 1},
{'source': 7, 'target': 10, 'value': 1},
{'source': 7, 'target': 7, 'value': 1}],
'multigraph': False,
'nodes': [{'id': 0, 'name': u'raymondkalonji'},
{'id': 1, 'name': u'raykaeng'},
{'id': 2, 'name': u'raymondkalonji2'},
{'id': 3, 'name': u'tester1cet'},
{'id': 4, 'name': u'tester2cet'},
{'id': 5, 'name': u'tester3cet'},
{'id': u'tester2cet'},
{'id': u'tester3cet'},
{'id': u'tester1cet'},
{'id': u'raykaeng'},
{'id': u'raymondkalonji2'}]}
How can I eliminate the repeated nodes?
You probably get repeated nodes because your user_connection.target() and user_connection.source() functions return the node name, not its id. When you call add_edge, if the endpoints do not exist in the graph, they are created, which explain why you get duplicates.
The following code should work.
for user_profile in UserProfile.objects.all():
source = user_profile.full_name3()
G.add_node(source, name=source)
for user_connection in Connection.objects.all():
target = user_connection.target()
source = user_connection.source()
G.add_edge(source, target, value=1)
data = json_graph.node_link_data(G)
Also note that you should dump the data object to json if you want a properly formatted json string. You can do that as follows.
import json
json.dumps(data) # get the string representation
json.dump(data, 'somefile.json') # write to file