简体   繁体   中英

How to use setState when finding intersection of list of lists in Flutter (Dart)

I have the following code. This is just created for being able to reproduce the problem, and I will explain what it does down below...

import 'package:flutter/material.dart';

class TestFile extends StatefulWidget {
  const TestFile({Key? key}) : super(key: key);

  @override
  _TestFileState createState() => _TestFileState();
}

class _TestFileState extends State<TestFile> {
  List<dynamic> a = [1, 2, 3, 4, 5];
  List<dynamic> b = [4, 5, 6, 7, 8];
  List<dynamic> c = [4, 5, 8, 9, 10];

  List<List<dynamic>> comb = [
    [],
    [],
    [],
  ];

  List<dynamic> result = [];

  Widget _itemWidget(idx, ml) {
    return InkWell(
      onTap: () {
        setState(() {
          comb[idx] = ml;

          result = comb
              .fold<Set>(
                  comb.first.toSet(), (a, b) => a.intersection(b.toSet()))
              .toList();
        });
      },
      child: Padding(
        padding: const EdgeInsets.fromLTRB(20, 5, 20, 5),
        child: Container(
          margin: const EdgeInsets.only(bottom: 3),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(15.0),
            color: Colors.blueAccent,
          ),
          child: Column(
            children: [
              Center(
                child: Text(idx.toString()),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: SingleChildScrollView(
        child: Column(
          children: [
            Text(comb.toString()),
            const SizedBox(height: 20),
            Text(result.toString()),
            _itemWidget(0, a),
            _itemWidget(1, b),
            _itemWidget(2, c),
          ],
        ),
      ),
    );
  }
}

The following is the initial state of the screen:

在此处输入图像描述

At top, we see the comb list of lists. In the beginning, it is empty.

Just under that, we see the result list, which is also empty in the beginning and it is supposed to show the intersection of lists from the comb list of lists.

And we have 3 buttons, with the names 0 , 1 , 2 accordingly.

First, I press on the button 0 . This adds the list a to comb[ 0 ] . And at this point, here is how the screen looks like:

在此处输入图像描述

So far, everything works as expected. The result list is empty because comb 1 and comb 2 are empty.

And now, I press on the button 1 . And here is how the screen looks like after pressing this button:

在此处输入图像描述

At top, we see the comb list of lists. Since I have pressed the buttons 0 and 1 so far, I see exactly what I expect to see from the comb . But at this point, I expect the result list to show [4, 5] , which are the common elements of comb[ 0 ] and comb 1 but what I see is an empty list [] , as also seen on the screen.

After spending quite a number of hours, I am not able to find the reason to this problem.

What do I need to change so that the result list is updated with the common values of selected lists based on which buttons the user presses on? What am I doing wrong here?

In your intersection logic, you are intersecting between sets [1, 2, 3, 4, 5], [4, 5, 6, 7, 8], and [] when buttons 0 and 1 are pressed. The common value between the three sets is the empty set. Change your intersection logic to filter out list elements that are empty:

          final nonEmpty = comb.where((x) => x.isNotEmpty);

          result = nonEmpty
              .fold<Set>(
                  nonEmpty.first.toSet(), (a, b) => a.intersection(b.toSet()))
              .toList();

You can also use reduce :

          result = comb
              .where((x) => x.isNotEmpty)
              .reduce((a, b) => a.toSet().intersection(b.toSet()).toList());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM