How to random select 3 element without repeating? - flutter

Random 3 Element with repeating
How to random select 3 element without repeating?
List<Question> imageList = [
Question(
index: 1,
image: 'assets/images/1.png',
),
Question(
index: 2,
image: 'assets/images/2.png',
),
Question(
index: 3,
image: 'assets/images/3.png',
),
Question(
index: 4,
image: 'assets/images/4.png',
),
Question(
index: 5,
image: 'assets/images/5.png',
),
];
This is Element List
getRandom =
List<Question>.generate(3, (_) => imageList[random.nextInt(imageList.length)]);
This is Random Function with repeating.

You could define an extension on List<T> so you can reuse it on all types of List:
List<String> alphabets = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
extension XList<T> on List<T> {
List<T> takeRandom(int n) {
return ([...this]..shuffle()).take(n).toList();
}
}
void main() {
print(alphabets.takeRandom(3));
print(alphabets.takeRandom(5));
print(alphabets.takeRandom(7));
}
Console log
[B, S, G]
[P, M, F, Q, K]
[U, M, R, C, Z, D, G]

Get the list count;
int total = imageList.length;
create index list numbers;
var listindex = List<int>.generate(total, (i) => i++);
shuffle list;
listindex .shuffle();
//result
[3, 6, 2, 0, 9, 1, 5, 7, 8, 4]
and get data from first 3 index list.
imageList[3].image
imageList[6].image
imageList[2].image

I solved this problem
Initialized with variable
List<Question> getRandom = [];
late Question correctElement;
Random random = Random();
Init State for first time run
#override
void initState() {
setRandom();
if (kDebugMode) {
print('getRandomNum is $getRandom & correctElement is $correctElement');
}
super.initState();
}
Used do while loop to unrepeate
Question shaffel() {
return imageList[random.nextInt(imageList.length)];
}
setRandom() {
getRandom.clear();
do {
Question data = shaffel();
if (getRandom.isEmpty) {
setState(() {
getRandom.add(data);
});
} else if (getRandom.contains(data)) {
} else {
setState(() {
getRandom.add(data);
});
}
} while (getRandom.length != 3);
correctElement = getRandom[random.nextInt(getRandom.length)];
}

Related

how to sum list values from API in flutter

Does anyone here know/have references/examples of how to add up the values in the list in Flutter. Thanks
use sum:
import 'package:collection/collection.dart';
void main() {
final list = [1, 2, 3, 4];
final sum = list.sum;
print(sum); // prints 10
}
Your question is similar to the question here, refer to it for more information
you can use .fold() method
fold method:
T fold<T>(T initialValue, T Function(T, Data) combine)
example for sum list of object:
void main() {
List<Data> listData = [
Data(count: 10, name: 'a'),
Data(count: 12, name: 'bc'),
Data(count: 21, name: 'abc'),
];
int sum = listData.fold(0, (int preValue, data) => preValue + data.count);
print(sum);// 43
}
class Data {
int count;
String name;
Data({required this.count, required this.name});
}

how to convert List<Model> to custom data in dart?

Is there any easy way convert List to other model data?
this is my model:
class Account {
String name;
double balance;
Account({required this.name, required this.balance});
}
class CategoryAccount {
String type;
List<Account> items;
CategoryAccount({required this.type, required this.items});
}
this is sourceData:
List<Account> sourceData = [
Account(name: 'cash', balance: 100),
Account(name: 'cash', balance: 200),
Account(name: 'bank', balance: 300),
Account(name: 'creditor', balance: 400),
];
I want sourceData convert to finalData:
List<CategoryAccount> finalData = [
CategoryAccount(
type: 'cash',
items: [
Account(name: 'cash', balance: 100),
Account(name: 'cash', balance: 200),
],
),
CategoryAccount(
type: 'bank',
items: [
Account(name: 'bank', balance: 300),
],
),
CategoryAccount(
type: 'creditor',
items: [
Account(name: 'creditor', balance: 300),
],
),
];
In Dart I saw the following method for a List : asMap(), but it's not doing what i expect: it use the list index as key. My questions:
Do you known anything in Dart libraries to do this ?
Solution without using a package:
List<CategoryAccount> finalData = [];
for (var se in sourceData) {
final index = finalData.indexWhere((fe) => fe.type == se.name);
if (index >= 0) {
finalData[index].items.add(se);
} else {
finalData.add(CategoryAccount(type: se.name, items: [se]));
}
}
Explanation:
Line 3: Loop through each elements in the sourceData variable
Line 4: Finding the index/position of the CategoryAccount object where the
type matches with the element name
Line 6: Adding the item to the
existing CategoryAccount object if match found (step 4)
Line 8: Else,
create a new CategoryAccount and add the current element
Using Set:
final uniqueEles = sourceData.map((e) => e.name).toSet(); // unique list/set of names [ cash, bank, creditor ]
for (var se in uniqueEles) {
finalData.add(CategoryAccount(
type: se,
items: sourceData.where((el) => el.name == se).toList(),
));
}
a little credit to Irfan Ganatra for the hint. :)
You can use collection package like this:
var grouped = groupBy(
sourceData,
(Account element) => element.name,
);
var finalData = grouped.entries
.map((e) => CategoryAccount(type: e.key, items: e.value))
.toList();
for (var element in finalData) {
print("type = ${element.type}");//cash, bank, creditor
}
and here is kid logic way
List<String> fetch_available_name_from_sourcedata() {
List<String> namelist = [];
for (int x = 0; x < sourceData.length; x++) {
if (!namelist.contains(sourceData[x].name))
namelist.add(sourceData[x].name);
}
return namelist;
}
void main() {
List<CategoryAccount> finaldata = [];
List<String> namelist = fetch_available_name_from_sourcedata();
for (int x = 0; x < namelist.length; x++) {
finaldata.add(CategoryAccount(
type: namelist[x],
items: sourceData
.where((element) => element.name == namelist[x])
.toList()));
}
//now you can see your final data as per your output...
}

Combining repeating items in a list

I have a list of items containing unique and repeating IDs, I want to sum the prices and display the number of the repeating IDs
class Model{
int id,price,count;
Model(this.id,this.price,this.count);
}
List<Model> list1 = [
Model(1,5000,10),
Model(2,1000,20),
Model(1,5000,5),
Model(2,5000,10),
];
List<Model> list2 = [];
I need the second list to be like this
list2 = [
Model(1,10000,15),
Model(2,6000,30),
];
try this :
void main() {
int sum = 0;
List<Model> list1 = [
Model(1, 5000, 10),
Model(2, 1000, 20),
Model(1, 5000, 5),
Model(2, 5000, 10),
];
List<Model> list2 = modelsWithoutRepeatingIdsButSumOfPricesAndAmount(
list1); // [Model(1,10000,15), Model(2,6000,30),]
}
List<Model> modelsWithoutRepeatingIdsButSumOfPricesAndAmount(
List<Model> modelList) {
Map<int, Model> map = {};
for (int index = 0; index < modelList.length; index += 1) {
Model current = modelList[index];
map[current.id] ??= Model(current.id, 0, 0);
map[current.id]!.price += current.price;
map[current.id]!.count += current.count;
}
return map.values.toList();
}
class Model {
int id, price, count;
Model(this.id, this.price, this.count);
}
Use reduce method to get the sum of a list
var total = [1, 2, 3].reduce((a, b) => a + b);
If you don't want to use reduce method you can also use .fold() there are couple more you can get them by importing dart collections package.

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]

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.