Say that I have a Map<String, int> containing entries and I would like to select the first entry with the highest value, see the example below:
Map<String, int> wordCount = {
'foo' : 3,
'bar' : 3,
'john' : 4,
'doe' : 3,
'four' : 4
}
What is the most efficient way to get john as it has the first highest value?
You can use something like this:
print(wordCount.entries.reduce((maxEntry, entry) {
return maxEntry.value < entry.value ? entry : maxEntry
}).key);
Something like this?
void main() {
Map<String, int> wordCount = {
'foo': 3,
'bar': 3,
'john': 4,
'doe': 3,
'four': 4
};
final nameWithHighestValue =
wordCount.entries.reduce((a, b) => a.value >= b.value ? a : b).key;
print(nameWithHighestValue); // john
}
Related
How can I reverse the key and value of the map?
for example, {1:a , 2:b , 3:c} => {a:1 ,b:2 ,c:3}
Try this piece of code:
Map<int, String> map = {1: "a", 2: "b", 3: "c"};
Iterable<String> values = map.values;
Iterable<int> keys = map.keys;
Map<String, int> reversedMap = Map.fromIterables(values, keys);
print(reversedMap); // {a:1 ,b:2 ,c:3}
You can do this:
const items = {1:'a' , 2:'b' , 3:'c'};
void main() {
final inverted = items.map((key, value) => MapEntry(value, key));
print(inverted);
}
It logs
{a: 1, b: 2, c: 3}
I have two Maps, bookingMap & reserveMap. Both maps have the same keys but different values. bookingMap is for the guest to book the seats whereas reserveMap is for the backend team. I want to compare the values of both maps with the help of their respective keys, if the values are equal I want to increment the totalSeats by +1 or +2. If the values don't match I want to subtract totalSeats by -1 or -2 respectively. Both maps have the same keys but map 1 can contain 10 out of 5 keys and Map 2 contains exactly 10 keys and values. If use if-else statements the code will be long. Is there a method or a way I'm missing?
The code below checks all the values, not the individuals.
import 'package:collection/collection.dart';
void main() {
compareValues();
}
void compareValues() {
int totalSeats = 0;
// Booking Map
Map<String, int> bookingMap = {
'c1': 1,
'c2': 2,
'c3': 3,
'c4': 5,
};
//Seat Map
Map<String, int> reserveMap = {
'c1': 1,
'c2': 2,
'c3': 3,
'c4': 4,
'c5': 6,
};
if (DeepCollectionEquality().equals(bookingMap.values, reserveMap.values)) {
totalSeats = totalSeats + 1;
} else {
totalSeats = totalSeats - 1;
}
print(totalSeats);
}
I think you need iterate through all keys and compare values. Something like that:
void compareValues() {
int totalSeats = 0;
Map<String, int> bookingMap = {
'c1': 1,
'c2': 2,
'c3': 3,
'c4': 5,
};
Map<String, int> reserveMap = {
'c1': 1,
'c2': 2,
'c3': 3,
'c4': 4,
'c5': 6,
};
var equals = true;
for (final kv in bookingMap.entries) {
if (reserveMap[kv.key] != kv.value) {
equals = false;
break;
}
}
if (equals) {
totalSeats = totalSeats + 1;
} else {
totalSeats = totalSeats - 1;
}
print(totalSeats);
}
With the help of and altering #chessmax answer I solved the issue with the following code.
void compareValues() {
int totalSeats = 0;
Map<String, int> bookingMap = {
'c1': 1,
'c2': 2,
'c3': 3,
'c4': 4,
'c5': 6,
};
Map<String, int> reserveMap = {
'c1': 1,
'c2': 2,
'c3': 3,
'c4': 4,
'c5': 66,
};
for (final kv in bookingMap.entries) {
if (reserveMap[kv.key] == kv.value) {
totalSeats = totalSeats + 1;
} else {
totalSeats = totalSeats - 1;
}
}
print(totalSeats);
}
I have a list of items from the orders by date, so based on its quantity I want to find what is the most sold product.
This is the class for my items
class CartItem{
String id;
String name;
String image;
int quantity;
double price;
CartItem({
this.id,
this.name,
this.image,
this.quantity,
this.price,
});
}
For example:
List<CartItem> list = orders.products;
list.forEach((element => print('${element.name} : ${element.quantity)');
It will print:
Dress : 1
Boots : 2
Trousers : 3
Dress : 2
Trousers : 2
So based on this example, how can I get the most sold product which is 'Trousers' and the sum of its quantity which is 5 for this case.
Thank you in advance.
You can covert the list to a map so you can see distinct items in the list. but rather than assigning the value to the key, if the key already exists, add the value
as:
list.forEach((item) => {
map2[item.name] = item.quantity + (map2[item.name] ?? 0)
});
you will get the output:
{Dress: 3, Boots: 2, Trousers: 5}
then finally you can sort the map like this:
var sortedKeys = map2.keys.toList(growable:false)
..sort((k1, k2) => map2[k2].compareTo(map2[k1]));
LinkedHashMap sortedMap = new LinkedHashMap
.fromIterable(sortedKeys, key: (k) => k, value: (k) => map2[k]);
print(sortedMap);
sorting os mentioned here as well How to sort map value?
then you can get the first element which is the product with the highest orders
hope this helps
Here is another example:
// Dart 2.6.1
main() {
List list = [
{
"name":"Dress",
"quantity" : 1
},{
"name":"Boots",
"quantity" : 2
},{
"name":"Trousers",
"quantity" : 3
},{
"name":"Dress",
"quantity" : 2
},{
"name":"Trousers",
"quantity" : 2
}
];
var products={
};
String mostSelling="";
int quantity=0;
list.forEach((e) {
if(products[e["name"]]== null){
products[e["name"]]= e["quantity"];
} else {
products[e["name"]]+= e["quantity"];
}
if(products[e["name"]] >quantity){
mostSelling= e["name"];
quantity = products[e["name"]];
}
}
);
print("$mostSelling : $quantity");
}
Output:
How I can get the most popular number from a list in dart without using any third party libraries?
var list = [0, 1, 1, 2, 2, 2, 3, 3, 4]; // most popular number is 2
If there are two or more popular numbers then the output should be a List with both values. Example:
One popular number:
var list = [0, 1, 1, 2, 2, 2, 3, 3, 4];
// Output should be [2]
Two or more popular numbers:
var list = [0, 1, 1, 2, 2, 2, 3, 3, 3];
// Output should be [2, 3]
Thank you in advance for your help!
This works...you can optimize it
var list = [1, 1, 2, 2, 3, 4, 5];
list.sort();
var popularNumbers = [];
List<Map<dynamic, dynamic>> data = [];
var maxOccurrence = 0;
var i = 0;
while (i < list.length) {
var number = list[i];
var occurrence = 1;
for (int j = 0; j < list.length; j++) {
if (j == i) {
continue;
}
else if (number == list[j]) {
occurrence++;
}
}
list.removeWhere((it) => it == number);
data.add({number: occurrence});
if (maxOccurrence < occurrence) {
maxOccurrence = occurrence;
}
}
data.forEach((map) {
if (map[map.keys.toList()[0]] == maxOccurrence) {
popularNumbers.add(map.keys.toList()[0]);
}
});
print(popularNumbers);
try this to count each element in list:
var list = [0, 1, 1, 2, 2, 2, 3, 3, 4];
var popular = Map();
list.forEach((l) {
if(!popular.containsKey(l)) {
popular[l] = 1;
} else {
popular[l] +=1;
}
});
I guess I found the solution.
Let me explain it to you:
I had queried through your list and checked whether the keys of the map contains the element or not. If the map does not contain the element as the key then, it will create a key from the element and pass 1 as the value. If the map does contain the element as a key then it will simply increment the value.
Once the map is ready, I had sorted the map values and stored them in a List. From the sorted map values I had taken the last element from the list of sorted values because we had sorted it in ascending order so the most popular value will be at last.
At last, I had queried through the map and check whether the value of the particular key is equal to the popularValue or not. If it is then we are adding the current key and value to the mostPopularValues list.
If I got something wrong please let me know.
void main() {
List list = [0, 1, 1, 1, 2, 2, 2, 3, 3, 4];
List mostPopularValues = [];
var map = Map();
list.forEach((element) {
if (!map.containsKey(element)) {
map[element] = 1;
} else {
map[element] += 1;
}
});
print(map);
// o/p : {0: 1, 1: 3, 2: 3, 3: 2, 4: 1}
List sortedValues = map.values.toList()..sort();
print(sortedValues);
// o/p : [1, 1, 2, 3, 3]
int popularValue = sortedValues.last;
print(popularValue);
// o/p : 3
map.forEach((k, v) {
if (v == popularValue) {
mostPopularValues.add("$k occurs $v time in the list");
}
});
print(mostPopularValues);
// o/p : [1 occurs 3 time in the list, 2 occurs 3 time in the list]
}
Not sure if that's the best solution, but it works pretty well. Let me know if there are any doubts.
final list = [0, 1, 1, 2, 2, 2, 3, 3, 4];
// Count occurrences of each item
final folded = list.fold({}, (acc, curr) {
acc[curr] = (acc[curr] ?? 0) + 1;
return acc;
}) as Map<dynamic, dynamic>;
// Sort the keys (your values) by its occurrences
final sortedKeys = folded.keys
.toList()
..sort((a, b) => folded[b].compareTo(folded[a]));
print('Most popular value: ${sortedKeys.first}'); // 1
print('Second most popular value: ${sortedKeys[1]}'); // 2
I have solved this problem by defining an extension on Iterable:
extension MostPopularItemsExtension<E> on Iterable<E> {
/// Returns the most popular items, where all items in the returned
/// list have the same number of occurances. If [this] is empty, returns an
/// empty list
///
/// Examples:
/// `[1,2,3,2].mostPopularItems() == [2]`
/// `[1,1,2,2].mostPopularItems() == [1,2]`
Iterable<E> mostPopularItems() {
if (isEmpty) return [];
final itemsCounted = <E, int>{};
for (final e in this) {
if (itemsCounted.containsKey(e)) {
itemsCounted[e] = itemsCounted[e]! + 1;
} else {
itemsCounted[e] = 1;
}
}
final highestCount = (itemsCounted.values.toList()..sort()).last;
return itemsCounted.entries
.where((e) => e.value == highestCount)
.map((e) => e.key);
}
}
The basic idea is to count all occurrences of each item in a Map object, get the highest count from this map and then return all items that have that specific number of occurrences.
I'd like a GroupBy that emits a new observable every time the key changes. Is there such a thing?
Something like this pseudocode:
[1,3,5,2,4,3,7] groupByConsecutive? oddEven
would produce
Observable[Observable[1,3,5],Observable[2,4],Observable[3,7]]
It took me a while to come up with something that did not rely on a Subject but I think this will do what you want:
new int[] { 1, 3, 5, 2, 4, 3, 7 }
.ToObservable()
.Publish(let =>
let
.GroupByUntil(
x => x % 2,
group => let.SkipWhile(x => x % 2 == group.Key)))
You could refactor the above into a more general extension method like this:
public static class EnumerableExtensions
{
public static IObservable<IGroupedObservable<TKey, TSource>> GroupByUntilChanged<TSource, TKey>(
this IObservable<TSource> source,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> comparer = null)
{
comparer = comparer ?? EqualityComparer<TKey>.Default;
return
source
.Publish(let =>
let
.GroupByUntil(
keySelector,
group => let.SkipWhile(x => comparer.Equals(keySelector(x), group.Key))));
}
}
And then call it like so:
new int[] { 1, 3, 5, 2, 4, 3, 7 }
.ToObservable()
.GroupByUntilChanged(x => x % 2)