多维阵列Flutter的排序与去重

xdyibdwo  于 2023-01-14  发布在  Flutter
关注(0)|答案(2)|浏览(261)

你好,我正在做一个项目,我有一个多维数组,名字和投票,这是数组

[[[Avoos, 0]], [[Abhiram MS, 1]], [[Amritha tg, 0]], [[usha, 2]]]

我从服务器获得了这个值,问题是每次刷新页面时,它都会将这些值再次存储在数组中(重复相同的值),因此它会得到如下所示的值

[[[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]]]

我想删除这些重复的值并根据投票对数组排序
这里是我的完整的代码使用的网页

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

7vux5j2d1#

这看起来很像是一个模型类会让100倍简单的任务,而不是使用一个多维数组,你可能会犯各种不同的错误,你可以把数据组合成一个单独的对象,并获得IDE的支持。
在您的示例中,该类可能如下所示:

class MyObject {
  final String name;
  final int votes;

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

}

当您在FutureBuilder中接收到数据时,您需要将列表的列表转换为这些对象的列表。这已经好得多了,但还有更多!
你可以实现= =和hashCode重写,这允许你比较两个相同的对象,并确定它们是否相等。

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

现在你可以在任何地方比较它们,只要写==

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

这也允许你不用存储返回的列表candidatesnapshot.data,你可以创建一个Set,它只允许任何给定的值在其中存储一次!如果你不想添加重复的值,这会自动地消除你添加重复的值。
要做到这一点,你必须修改FutureBuilder之后的代码。我不想撒谎,我真的不明白那里发生了什么,因为你似乎要为Stream返回的每个对象创建一个新的FutureBuilder。无论哪种方式,我认为最好是简单地循环流中的值,并将数据添加到Set
现在,您还可以轻松地对MyObjects的集合进行排序,只需将值作为列表获取,然后使用listsx 1 m11n1x方法。

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

由于类型只有intstring,所以可以使用它们的compareTo方法自动排序,要颠倒顺序,只需在排序函数上颠倒ab即可!
如果你因为某种原因不能使用一个模型类--我 * 真的 * 不明白你为什么不能--仍然可以通过以下方法过滤掉重复的:

  • 每次获得新数据时覆盖列表(使用x = ..代替x.add()
  • 通过为每个新值循环列表/在列表上使用.contains()方法来检查重复项

至于排序,您可以使用.sort()方法,您只需要使用[index]语法,而不是右侧的对象字段,这确实也不是很好。

yyyllmsg

yyyllmsg2#

要删除重复值并根据投票对数组进行排序,可以使用toSet()函数,然后使用toList()将其转换回列表。这将删除任何重复值。然后可以使用sort()函数根据投票对数组进行排序。

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

首先将candidatearrayreal转换为一个集合,这将删除所有重复的值,然后将其转换回列表,接下来,它将使用sort()函数和一个比较器函数(比较两个候选者的投票)根据每个子列表的第二个元素(即投票数)对列表进行排序。
您可以将这段代码放在refresh()函数中,这样它就会在用户每次刷新页面时执行。
此外,您可以将candidatearray.clear();代码移动到initState()函数,这将在用户每次进入CloseElec页面时清除阵列。

相关问题