Home > other >  Sorting and removing duplicates of multi dimensional array flutter
Sorting and removing duplicates of multi dimensional array flutter

Time:01-13

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]}'),
                      );
                    }),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

CodePudding user response:

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:

class MyObject {
  final String name;
  final int votes;

  MyObject({required this.name, required this.votes});

}

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 == and hashCode 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:

@override
bool operator ==(covariant MyObject other) {
  if (identical(this, other)) return true;
  return 
    other.name == name &&
    other.votes == votes &;
}

@override
int get hashCode {
  return name.hashCode ^
    votes.hashCode;
}

Now you can compare them anywhere by simply writing ==:

MyObject a = MyObject(name: "test", votes: 10);
MyObject b = MyObject(name: "test", votes: 10);
MyObject c = MyObject(name: "xyz", votes: 0);
print(a == b); // true
print(a == c); // false

What this also allows you to do is instead of storing the returned list candidatesnapshot.data, you can create a Set, 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 new FutureBuilder for every object returned by the Stream. Either way, I think it would be best to simply loop over the values from the stream and add the data to the Set.

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.

Set<MyObjects> m = {...}; // your data goes here
final sortedList = m.toList()..sort((a, b) => a.votes.compareTo(b.votes));

Since the types are only int and string, you can use their compareTo methods and automatically sort them. To reverse the order, simply reverse a and b 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:

  • overwriting the list every time you get new data (using x = .. instead of x.add()
  • checking for duplicates by looping over the list for every new value / using the .contains() method on the list

As 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.

CodePudding user response:

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 using toList(). This will remove any duplicate values. Then you can use the sort() function to sort the array according to the votes.

candidatearray = candidatearrayreal.toSet().toList();
candidatearray.sort((a, b) => a[1].compareTo(b[1]));

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 the sort() 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 the initState() function, this will clear the array every time the user enters the CloseElec page.

  • Related