Hello I am working on a project here I have a multidimensional array with name and votes this is the array
[[[Avoos, 0]], [[Abhiram MS, 1]], [[Amritha tg, 0]], [[usha, 2]]]
I get this from the server,the problem is every time I refresh the page it stores these values again in the array(repeating the same values) so its getting something like this
[[[Avoos, 0]], [[Abhiram MS, 1]], [[Amritha tg, 0]], [[usha, 2]], [[Amritha tg, 0]], [[Abhiram MS, 1]], [[Avoos, 0]], [[usha, 2]], [[Amritha tg, 0]], [[Abhiram MS, 1]], [[Avoos, 0]], [[usha, 2]]]
I want to remove these repeated values and sort this array according to the votes
here is my complete code used on the page
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:web3dart/web3dart.dart';
import '../../services/Auth.dart';
import '../../services/IntoLogin.dart';
import '../../services/functions.dart';
class CloseElec extends StatefulWidget {
final Web3Client ethClient;
final String electionName;
final String electionAdress;
const CloseElec({Key? key, required this.ethClient, required this.electionName, required this.electionAdress}) : super(key: key);
@override
State<CloseElec> createState() => _CloseElecState();
}
class _CloseElecState extends State<CloseElec> {
void refresh() {
setState(() {
//candidatearray.clear();
candidatearray =candidatearrayreal.toSet().toList();
});
}
Future<void> signOut() async {
if (!mounted) return;
await Auth().signOut();
if (!mounted) return;
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => IntroLogin()),
(route) => false);
}
late String winner = 'No candidate';
late int winnervotes = 0;
late int row = 5;
late int col = 5;
var candidatearray = [] ;
var candidatearrayreal = [] ;
@override
void initState() {
candidatearray.clear();
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(gradient:
LinearGradient(colors: [
Color(0xFF516395),
Color(0xFF614385 ),
])),
child: Scaffold(
appBar:AppBar(
backgroundColor: Colors.transparent,
leading: IconButton(onPressed: () {
signOut();
}, icon: const Icon(Icons.logout_sharp),),
title: const Text('Election progress'),
actions: [
IconButton(onPressed: () {
refresh();
}, icon: const Icon(Icons.refresh))
],
),
body: SingleChildScrollView( //Here we are getting the whole candidate details
child: Column(
children: [
Container(margin: const EdgeInsets.only(bottom: 56),
child: SingleChildScrollView( // this stream builder will give the number of items/candidates
child: StreamBuilder<List>(stream: getCandidatesNum(widget.ethClient, widget.electionAdress).asStream(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator(),);//circular bar for waiting
} else {
return Column(
children: [ // here we will get all candidates using a loop
for (int i = 0; i < snapshot.data![0].toInt(); i++)
FutureBuilder<List>( // call to get candidate info
future: candidateInfo(i, widget.ethClient, widget.electionAdress),
builder: (context, candidatesnapshot) {
if (candidatesnapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator(),);
} else {
// logic to decide the winner
if(candidatesnapshot.data![0][1].toInt() > winnervotes){
winnervotes = candidatesnapshot.data![0][1].toInt();
winner = candidatesnapshot.data![0][0];
}else if(candidatesnapshot.data![0][1].toInt() == winnervotes){
winner = candidatesnapshot.data![0][0];
}
candidatearrayreal.add(candidatesnapshot.data);
// print(candidatesnapshot.data);
return Container(
padding: const EdgeInsets.all(12),
margin: const EdgeInsets.all(12),
decoration: const BoxDecoration(
boxShadow: [
BoxShadow(color: Color(0xFF7F5A83),
offset: Offset(-11.9, -11.9),
blurRadius: 39,
spreadRadius: 0.0,
),
BoxShadow(color: Color(0xFF7F5A83),
offset: Offset(11.9, 11.9),
blurRadius: 39,
spreadRadius: 0.0,
),
],
borderRadius: BorderRadius.all(Radius.circular(10)),
gradient: LinearGradient(colors: [
Color(0xFF74F2CE),
Color(0xFF7CFFCB),
])),
child: ListTile(
title: Text('Name: ${candidatesnapshot.data![0][0]}',
style: const TextStyle(color: Colors.purple)),
subtitle: Text('Votes: ${candidatesnapshot.data![0][1]}',
style: const TextStyle(color: Colors.purple)),
),
);
}
})
],
);
}
},
),
),
),
const SizedBox(height: 12,),
Text('The winner of the election is : $winner with votes $winnervotes',style: const TextStyle(color: Colors.white)),
const SizedBox(height: 16,),
SizedBox(
height: MediaQuery.of(context).size.height,
width: double.infinity,
child: ListView.builder(
itemCount:candidatearray.length,
itemBuilder: (context,index){
for (var i = 0; i < candidatearray.length; i++) {
candidatearray.sort((a, b) {
print(candidatearrayreal);
//print(b[0][1]);
return int.parse(a[0][1].toString()).compareTo(int.parse(b[0][1].toString()));
});
}
return ListTile(
title: Text('${candidatearray[index][0][0]}'),
subtitle:Text('votes : ${candidatearray[index][0][1]}'),
);
}),
),
],
),
),
),
);
}
}
2
Answers
To remove the repeated values and sort the array according to the votes, you can use the
toSet()
function and then convert it back to a list usingtoList()
. This will remove any duplicate values. Then you can use thesort()
function to sort the array according to the votes.This will first convert the
candidatearrayreal
to a set, which will remove any duplicate values, and then convert it back to a list. Next, it will sort the list according to the second element of each sublist (which is the number of votes) using thesort()
function and a comparator function that compares the votes of the two candidates.You can put this piece of code in the
refresh()
function, so it will be executed every time the user refreshes the page.Also, you can move the
candidatearray.clear();
code to theinitState()
function, this will clear the array every time the user enters the CloseElec page.This seems a lot like a task a model class would make 100 times easier. Instead of using a multi-dimensional array where you might make various different mistakes, you can combine the data into a single object and get IDE support too.
In your case, that class could look like this:
When you receive the data in your
FutureBuilder
you will need to transform the list of lists into a list of these objects. This is already much better, but there’s more!You can implement the
=
= andhashCode
overrides which allows you to compare two of the same objects and determine whether they are equal or not. Write this in your model class too:Now you can compare them anywhere by simply writing
==
:What this also allows you to do is instead of storing the returned list
candidatesnapshot.data
, you can create aSet
, which only allows any given value to be stored inside it a single time! This automatically eliminates you from adding duplicates, if that isn’t what you want.To do this, you’re going to have to fix up the code after your
FutureBuilder
. I’m not going to lie, I don’t really understand what’s going on there since you seem to be creating a newFutureBuilder
for every object returned by theStream
. Either way, I think it would be best to simply loop over the values from the stream and add the data to theSet
.Now, you can also easily sort this set of your
MyObjects
. Simply get the values as a list and then use the lists.sort
method.Since the types are only
int
andstring
, you can use theircompareTo
methods and automatically sort them. To reverse the order, simply reversea
andb
on the sort function!If you for some reason can’t use a model class – and I really don’t see why you couldn’t – it is still possible to filter out duplicates by either:
x = ..
instead ofx.add()
.contains()
method on the listAs for sorting, you can use the
.sort()
method, you’ll just have to use a[index]
syntax instead of object fields on the right side, which really isn’t great either.