List to nested list by a field [duplicate] - dart

This question already has an answer here:
Create Lists from List based on Matching Object Properties
(1 answer)
Closed 1 year ago.
I have a list:
List<MyObject> list = [MyObject(title: "1a", genre:"1g"), MyObject(title: "1b", genre:"1g"), MyObject(title: "2a", genre:"2g"), MyObject(title: "2b", genre:"2g")]
I want to convert this list into a nested list so that my nested list view can use the data. I want the convertion to be done by genre field. After the convertion the output should be the following:
List<List<MyObject>> newList = [[MyObject(title: "1a", genre:"1g"), MyObject(title: "1b", genre:"1g")], [MyObject(title: "2a", genre:"2g"), MyObject(title: "2b", genre:"2g")]]
Notice:
newList[0] == [MyObject(title: "1a", genre:"1g"), MyObject(title: "1b", genre:"1g")]
newList[1] == [MyObject(title: "2a", genre:"2g"), MyObject(title: "2b", genre:"2g")]
is there any short one liners i can use to do this with my list variable? I dont wanna write a long, inefficient code, im new to dart so i could not figure this. Any help would be very cool.

add import:
import "package:collection/collection.dart";
then
final List<MyObject> list = [MyObject(title: "1a", genre:"1g"), MyObject(title: "1b", genre:"1g"), MyObject(title: "2a", genre:"2g"), MyObject(title: "2b", genre:"2g")];
final map = groupBy(list, (e) => e.genre);
final finalList = map.values.toList();

Here is the solution I suggested from my comment to create Map indexed by genre then get its values.
class MyObject {
final String title;
final String genre;
MyObject({this.title, this.genre});
String toString() => "{title: ${title}, genre: ${genre}}";
}
List<MyObject> list = [
MyObject(title: "1a", genre: "1g"),
MyObject(title: "1b", genre: "1g"),
MyObject(title: "2a", genre: "2g"),
MyObject(title: "2b", genre: "2g")
];
void main() {
var myMap = <String, List<MyObject>>{};
for (var item in list) {
if (myMap.containsKey(item.genre) == false) {
myMap[item.genre] = <MyObject>[item];
} else {
myMap[item.genre].add(item);
}
}
print(myMap.values);
}

Related

Fetch random items from list without duplicate or repetition - Dart

I'm trying to fetch the randomly specific number of items from one list and add them to the other list but without duplication.
For example: pick three random items from the list randomly and put them into another list. This is what I have achieved so far but this could pick the duplicate item again.
List itemList = ['NAME1', 'NAME2', 'NAME3', 'NAME4', 'NAME3', 'NAME5', 'NAME2'];
List randomItems = [];
for(var i=0; i<=2; i++){ // run the loop for three times
int randomNumber = Random().nextInt(itemList.length); //generate random number within itemList range
randomItems.add(itemList[randomNumber]); // duplication occur, for example: NAME2 could be added two times
}
There are several steps we can do to solve this problem. First, we want to get rid of the duplicate elements in the list. We can here do that by converting the list to a Set:
List<String> itemList = [
'NAME1',
'NAME2',
'NAME3',
'NAME4',
'NAME3',
'NAME5',
'NAME2'
];
Set<String> itemSet = itemList.toSet();
print(itemSet); // {NAME1, NAME2, NAME3, NAME4, NAME5}
Then, we want to extract 3 random elements from this new Set in such a way that we can't select the same element twice. The easiest way to solve this is by shuffle the elements randomly and then take elements from our collection. But Set does not have the concept of any specific "order" and we can't therefore shuffle our Set.
So let's convert our Set back to a List:
Set<String> itemSet = itemList.toSet();
List<String> itemListFromSet = itemSet.toList();
print(itemListFromSet); // [NAME1, NAME2, NAME3, NAME4, NAME5]
We can then shuffle this new list:
itemListFromSet.shuffle();
print(itemListFromSet); // [NAME3, NAME2, NAME4, NAME5, NAME1]
If we then want 3 random selected elements, we can just take 3 elements from this randomly ordered list. So e.g. (take returns an iterable which we then makes a new list of):
List<String> randomItems = itemListFromSet.take(3).toList();
A complete solution would look like:
void main() {
List<String> itemList = [
'NAME1',
'NAME2',
'NAME3',
'NAME4',
'NAME3',
'NAME5',
'NAME2'
];
Set<String> itemSet = itemList.toSet();
List<String> itemListFromSet = itemSet.toList();
itemListFromSet.shuffle();
List<String> randomItems = itemListFromSet.take(3).toList();
print(randomItems); // [NAME5, NAME2, NAME4]
}
Which can be reduced down to:
void main() {
List<String> itemList = [
'NAME1',
'NAME2',
'NAME3',
'NAME4',
'NAME3',
'NAME5',
'NAME2'
];
List<String> randomItems =
(itemList.toSet().toList()..shuffle()).take(3).toList();
print(randomItems); // [NAME3, NAME4, NAME2]
}

DART : Merge two maps with identical key

Suppose I have these maps:
Map<int,List<String>> firstMap = {1:["a", "b"]};
Map<int,List<String>> secondMap = {2:["c"]};
Map<int,List<String>> thirdMap = {1:["d"]};
I want to merge them without overwriting values with same key to have this output:
{1: [a, b, d], 2: [c]
I used both spread operator and adAll method and both overwrite the value for key 1 to have {1: [d], 2: [c]}
instead of {1: [a, b, d], 2: [c].
void main() {
Map<int, List<String>> firstMap = {1: ["a", "b"]};
Map<int, List<String>> secondMap = {2: ["c"]};
Map<int, List<String>> thirdMap = {1: ["d"]};
var mergedMap = <int, List<String>>{};
for (var map in [firstMap, secondMap, thirdMap]) {
for (var entry in map.entries) {
// Add an empty `List` to `mergedMap` if the key doesn't already exist
// and then merge the `List`s.
(mergedMap[entry.key] ??= []).addAll(entry.value);
}
}
print(mergedMap); // Prints: {1: [a, b, d], 2: [c]}
}

How to convert list into string with quotes Dart

I have a list and want it as a string with quotes List myList = [1,2,3]
require O/P as List myList = ["1","2","3"]
i think this works as you need!
void main(List<String> arguments) {
List myList = [1, 2, 3];
List myNewList = [];
myList.forEach((item) {
myNewList.add("\'$item\'");
});
}
so the print of myList would be [1, 2, 3]
and the print of myNewList would be ['1', '2', '3'].
by the way...
The order of the quotation signs is arbitrary and the meaning of
"\'$item\'"
is the same as
'\"$item\"'
The difference is that your output from
"\'$item\'"
would be
['1', '2', '3']
and the output of
'\"$item\"'
would be
["1", "2", "3"].
I think you want something like this:
List<String> myList = <String>["'1'","'2'","'3'"];
Or you can use it this way:
List<String> myList = <String>['\'1'\','\'2'\','\'3\''];

How to sort map value?

I have this map:
var temp= {
'A' : 3,
'B' : 1,
'C' : 2
};
How to sort the values of the map (descending). I know, I can use temp.values.toList()..sort().
But I want to sort in context of the keys like this:
var temp= {
'B' : 1,
'C' : 2
'A' : 3,
};
This example uses a custom compare function which makes sort() sort the keys by value. Then the keys and values are inserted into a LinkedHashMap because this kind of map guarantees to preserve the order.
Basically the same as https://stackoverflow.com/a/29629447/217408 but customized to your use case.
import 'dart:collection';
void main() {
var temp= {
'A' : 3,
'B' : 1,
'C' : 2
};
var sortedKeys = temp.keys.toList(growable:false)
..sort((k1, k2) => temp[k1].compareTo(temp[k2]));
LinkedHashMap sortedMap = new LinkedHashMap
.fromIterable(sortedKeys, key: (k) => k, value: (k) => temp[k]);
print(sortedMap);
}
Try it on DartPad
The SplayTreeMap has a named constructor which accepts map and a comparator which is used to sort given map while building new map. Since SplayTreeMap is a descendant of Map you can easily substitute it.
import 'dart:collection';
void main() {
var unsorted = {'A': 3, 'B': 1, 'C': 2};
final sorted = SplayTreeMap.from(
unsorted, (key1, key2) => unsorted[key1].compareTo(unsorted[key2]));
print(sorted);
}
final Map<String, ClassCategory> category;
...
Map<String, ClassCategory> sorted = SplayTreeMap.from(category,
(key1, key2) => category[key1]!.title.compareTo(category[key2]!.title));
for (var item in sorted.entries) {
...
}

Store enum as comma separated list

I am trying to save an enum as a comma-separated list in a DB.
I know I can do something like this to actually store a comma separated list:
part.MyProperty = new[] {"foo", "bar"};
and the DB would have an entry "foo, bar".
What I don't know how to do is how to store an enum, such as:
public enum Choices { Choice1, Choice2, Choice3 }
I gather I have to use Parse and ToString to use the enum values, but I am not sure how to do it.
This doesn't seem right:
part.MyProperty = new[] return from name in Enum.GetNames(typeof(T))
let enumValue = Convert.ToString((T)Enum.Parse(typeof(T), name, true))
Any thoughts?
What's wrong with part.MyProperty = Enum.GetNames(typeof(Choices)); ?
To get a comma separated list, use String.Join:
string csvEnums = string.Join(",", Enum.GetNames(typeof(Choices)));
String.Join(",", Enum.GetNames(typeof(Choices)));
Also you can build your own utitlity method that will get enums name in more nice syntax:
public static TEnum[] GetEnumValues<TEnum>() where TEnum : struct {
return (TEnum[])Enum.GetValues(typeof(TEnum));
}
and then:
Choices[] choices = GetEnumValues<Choices>();
or
part.MyProperty = GetEnumValues<Choices>().Select(n=>n.ToString()).ToArray();
[Flags]
public enum Choices {
Choice1 = 1,
Choice2 = 2,
Choice3 = 4
}
Choices a = Choices.Choice1 | Choices.Choice3;
Console.WriteLine(a.ToString());
outputs: Choice1, Choice3

Resources