How to join the values in-between two values in a list - flutter

I have this list [null, 3, 5, null] and I want to join the values in-between nulls and put it into the same list
For example:
[null, 3, 5, null] into [null, 35, null]
I made this one extension that groups all the values between two nulls
extension GroupByNull<T> on List<T> {
List<List<T>> groupByNull() {
final groupedList = <List<T>>[];
var list = this;
for (var i = 0; i < list.length; i++) {
if (list[i] == null) {
if (i > 0) {
groupedList.add(list.sublist(0, i));
}
list = list.sublist(i + 1);
i = 0;
}
}
if (list.isNotEmpty) {
groupedList.add(list);
}
return groupedList;
}
}
Which returns [[3, 5]] for [null, 3, 5, null]... But I want it to be joined together and added to the original list in the same index
How can I solve this...
thank you.

Note that you can't operate on an arbitrary List<T> because there's no general way to combine two elements of some arbitrary type T. What you want could make sense for List<int?> or maybe List<String?>. (Or maybe it could work on an arbitrary List<T> input if you want a List<String?> output.)
Assuming that you want to operate on List<int?>, then basically as you iterate over your input list, keep track of your current accumulated value. If you encounter null, add the current value (if any) to your output List along with the null. Don't forget to add the current accumulated value (if any) when you're done iterating in case there isn't a final null element.
extension GroupByNull on List<int?> {
List<int?> groupByNull() {
var result = <int?>[];
int? currentValue;
for (var element in this) {
if (element != null) {
currentValue = (currentValue ?? 0) * 10 + element;
} else {
if (currentValue != null) {
result.add(currentValue);
currentValue = null;
}
result.add(currentValue);
}
}
if (currentValue != null) {
result.add(currentValue);
}
return result;
}
}
void main() {
print([null, 3, 5, null].groupByNull()); // Prints: [null, 35, null]
print([3, 5, null].groupByNull()); // Prints: [35, null]
print([3, 5, null, null].groupByNull()); // Prints: [35, null, null]
print([null, 3, 5].groupByNull()); // Prints: [null, 35]
print([null, null, 3, 5].groupByNull()); // Prints: [null, null, 35]
print([null, 0, 0, 0, null].groupByNull()); // Prints: [null, 0, null]
print([null, 1, 2, null, 3, 4, null]
.groupByNull()); // Prints: [null, 12, null, 34, null]
print([null].groupByNull()); // Prints: [null]
print([null, null].groupByNull()); // Prints: [null, null]}
}

You can use this solution.
extension GroupByNull<T> on List<T> {
List groupByNull() {
final groupedList = [];
var list = this;
list.removeWhere( (value) => value == null); // remove all null values
groupedList.add(int.parse(list.join(""))); // combine number left in list
groupedList.insert(0,null); // add null
groupedList.add(null);
return groupedList;
}
}

Related

Flutter, how to using square brackets to access dynamic key of list

When I use https://dartpad.dev/?id
import 'package:intl/intl.dart';
void main() {
final matches = [
{
"match_id": 6604501658,
"player_slot": 129,
"radiant_win": false,
"duration": 2020,
"game_mode": 22,
"lobby_type": 7,
"hero_id": 19,
"start_time": 1654520510,
"version": 21,
"kills": 13,
"deaths": 7,
"assists": 17,
"skill": null,
"xp_per_min": 780,
"gold_per_min": 604,
"hero_damage": 36271,
"tower_damage": 10042,
"hero_healing": 0,
"last_hits": 211,
"lane": 2,
"lane_role": 2,
"is_roaming": false,
"cluster": 156,
"leaver_status": 0,
"party_size": 1
},
{
"match_id": 6604451816,
"player_slot": 4,
"radiant_win": false,
"duration": 1242,
"game_mode": 22,
"lobby_type": 7,
"hero_id": 52,
"start_time": 1654518740,
"version": 21,
"kills": 7,
"deaths": 4,
"assists": 1,
"skill": null,
"xp_per_min": 540,
"gold_per_min": 472,
"hero_damage": 14678,
"tower_damage": 2111,
"hero_healing": 0,
"last_hits": 136,
"lane": 2,
"lane_role": 2,
"is_roaming": false,
"cluster": 156,
"leaver_status": 0,
"party_size": 1
}
];
final List<String> extraList = ['kills','deaths','assists','gold_per_min','xp_per_min','last_hits','hero_damage','hero_healing','tower_damage','duration'];
for(var i in extraList) {
print(averMax(matches, i));
}
}
String averMax(dynamic matches, String field) {
final dynamic matchesMap = matches.map((match) => match[field]);
final dynamic matchesReduce = matchesMap.reduce((cur, total) => cur + total);
return field != 'duration' ?
greaterNum((matchesReduce / 20).round(), 1000, 'K') :
(matchesReduce / 20).toString();
}
String greaterNum(double num, int gN, String unit) {
var minus = '';
if (num < 0) {
minus = '-';
}
num = (num).abs();
if (num > gN) {
final newNum = (num / gN).toStringAsFixed(1);
return '$minus$newNum$unit';
} else {
return '$minus$num';
}
}
Works
However at flutter:
Flutter the PlayerMatches is from API which is List
I want to map the extraList value as key in the matches to dynamic get data and pass to a List View
In dartPad works, however in flutter cant access data use square brackets.
My question:
Could I access the Object key dynamically like javascript?
Thanks for #lepsch who help me
At flutter,
return match.toJson()[field];
Flutter doesn't support reflection/mirrors so it's not possible to get a property by name. This is on purpose so Flutter knows at compile time all kinds of access to an object that exists and can optimize it accordingly by tree-shaking (Strip out anything that isn’t used).
One solution could be converting PlayerRecentMatch to JSON as a Map<String, dynamic>. This way you can access the Map with the brackets operator.
Another way though to implement your function is using a first-class function as an argument to get the property instead of the property name. Take a look below:
class PlayerRecentMatch {
final double score;
const PlayerRecentMatch({required this.score});
}
double averMax(
List<PlayerRecentMatch> matches,
double Function(PlayerRecentMatch) getProperty, // <- Here
) {
final matchesMap = matches.map((match) {
return getProperty(match);
}).toList();
final matchesReduce = matchesMap.reduce((sum, total) => sum + total);
return matchesReduce / matches.length;
}
void main() {
final matches = [
PlayerRecentMatch(score: 1),
PlayerRecentMatch(score: 2),
PlayerRecentMatch(score: 3),
PlayerRecentMatch(score: 4),
];
print('averMax = ${averMax(matches, (match) => match.score)}');
}
https://dartpad.dev/?id=44cbecffd6f86f1714a4553101a16001

Dart - Comparing two Map values

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);
}

Can I sort List<dynamic> in dart

Can I sort List<dynamic> in dart?
List<dynamic> list= [9,10,'Plus One'];
list.sort();
print(list);
I expect the result like 9,10,'Plus One' Or 'Plus One', 9, 10
You just need to provide a callback to List.sort that orders heterogeneous types the wya you want. For example, assuming that your heterogeneous List contains only ints and Strings, you could do:
List<dynamic> list = [9, 10, 'Plus One'];
list.sort((a, b) {
if ((a is int && b is int) || (a is String && b is String)) {
return a.compareTo(b);
}
if (a is int && b is String) {
return -1;
} else {
assert(a is String && b is int);
return 1;
}
});
print(list);
If you need to potentially handle other types, you will need to adjust the callback appropriately.
If you want to sort dynamic list and want string before number(int or double) try
this code:
List<dynamic> list = [
'mahmoud',
14,
'zika',
9,
10,
'plus One',
5,
'banana',
1,
2.5,
'apple',
2,
1.2,
'ball'
];
list.sort(
(a, b) {
if ((a is num && b is num) || (a is String && b is String)) {
return a.compareTo(b);
}
// a Greater than b return 1
if (a is num && b is String) {
return 1;
}
// b Greater than a return -1
else if (a is String && b is num) {
return -1;
}
// a equal b return 0
return 0;
},
);
print(list);// [apple, ball, banana, mahmoud, plus One, zika, 1, 1.2, 2, 2.5, 5, 9, 10, 14]

How to remove null and 0 from the map?

I tried to remove NULL from the map for a long time.....
sortedMap.removeWhere((key, value) => value == "NULL");
sortedMap.removeWhere((key, value) => value == NULL);
...however, this could not be done, and I decide to set the default value "No Data", this solved the problem.
sortedMap.removeWhere((key, value) => value == "No Data");
and, this solved the problem! Now, I can’t remove the value "0" from the map now.
sortedMap.removeWhere((key, value) => value == "0");
sortedMap.removeWhere((key, value) => value == 0);
This's my map:
{h_1: 0, h_2: 1, h_3: 1, h_4: 1, h_5: 0, h_6: 1}
Please, tell me.
How to solve this problem?
Thanks for any help
Is it same solution like yours?
In my case, it works well.
void main() {
Map data = {'h_1': 0, 'h_2': 1, 'h_3': 1, 'h_4': 1, 'h_5': 0, 'h_6': 1};
print(data);
data.removeWhere((k, v) => v == 0);
print(data);
}
What is NULL? Is it perhaps null you are looking for to remove?
(Null in the case below is a class from dart:core)
import 'package:flutter_test/flutter_test.dart';
void main() {
test(
'Remove null',
() {
Map<String, dynamic> map = {
'a': 1,
'b': 2,
'c': null,
'd': 4,
};
print(map);
map.removeWhere((key, value) => value == Null);
print(map);
map.removeWhere((key, value) => value == null);
print(map);
// assert
},
);
}
This prints:
{a: 1, b: 2, c: null, d: 4}
{a: 1, b: 2, c: null, d: 4}
{a: 1, b: 2, d: 4}
✓ Remove null

Get most popular value in a list

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.