简体   繁体   中英

How can I search a list of widgets efficiently with TextField input, by partial matches alphabetically in Flutter?

I have a TextField widget working with ScrollablePositionedList.builder (package).

When the user inputs characters into the TextField it will then automatically scroll the list to that word in my list of widgets which are organized alphabetically.

When there is not an exact match however, I am trying to search alphabetically by each charater input one by one to the closest match. (eg so "ca" would scroll to the first word starting with “ca" like "cat" - rather than the first word that just contains "ca" somewhere in say the middle of the word).

I can do this by using if statements comparing character by character - however this appears very inefficient and increased levels of code for increasing potential character lengths input, where no exact match occurs.

QUESTION: As this appears a very standard search method, is there a better pattern / method / standard approach that can achieve the above result and could handle any length range of characters input? I have searched for a solution for Flutter but can't seem to find one.

Thank you!

Here is the relevant section of example code of my current solution to search alphabetically (ie this would need to keep increasing for potential longer matches)...

 else if (_inputtedText.length == 2) {
            for (int i = 0; i < _expandedTiles.length; i++) {
              if (_inputtedText[0] == _expandedTiles[i].tileModel.word![0]) {
                if(_inputtedText[1] == _expandedTiles[i].tileModel.word![1]){
                  _itemScrollController.scrollTo(
                      curve: Curves.easeInOut,
                      index: i,
                      duration: Duration(milliseconds: 2000));
                  break;
                }
              }

/// code omitted

/// And a fuller version of code for more context


class _AllWordsState extends State<AllWords> {
  final TextEditingController _textEditingController = TextEditingController();
  final ItemScrollController _itemScrollController = ItemScrollController();

  String _inputtedText = "";

  List<Map> _allWords = [];
  List<ExpandedTile> _expandedTiles = [];

  TileModel _modelTapped = TileModel();

  @override
  void initState() {
    WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      _textEditingController.addListener(() {
        for (int i = 0; i < _expandedTiles.length; i++) {
          if (_inputtedText.isEmpty) {
            return;
          } else if (_inputtedText == _expandedTiles[i].tileModel.word!) {
            _itemScrollController.scrollTo(
                curve: Curves.easeInOut,
                index: i,
                duration: Duration(milliseconds: 2000));
            return;
          }
          else if (_inputtedText.length == 1) {
            for (int i = 0; i < _expandedTiles.length; i++) {
              if (_inputtedText[0] == _expandedTiles[i].tileModel.word![0]) {
                _itemScrollController.scrollTo(
                    curve: Curves.easeInOut,
                    index: i,
                    duration: Duration(milliseconds: 2000));
                break;
              }
            }
          }
          else if (_inputtedText.length == 2) {
            for (int i = 0; i < _expandedTiles.length; i++) {
              if (_inputtedText[0] == _expandedTiles[i].tileModel.word![0]) {
                if(_inputtedText[1] == _expandedTiles[i].tileModel.word![1]){
                  _itemScrollController.scrollTo(
                      curve: Curves.easeInOut,
                      index: i,
                      duration: Duration(milliseconds: 2000));
                  break;
                }
              }
            }
          }

          else if (_expandedTiles[i]
              .tileModel
              .word!
              .contains(_inputtedText)) {
            _itemScrollController.scrollTo(
                curve: Curves.easeInOut,
                index: i,
                duration: Duration(milliseconds: 2000));
            break;
          }
        }
      });
    });

    _setUpDatabase();

    super.initState();
  }

/// code omitted

child: ScrollablePositionedList.builder(
                  itemScrollController: _itemScrollController,
                  itemCount: _expandedTiles.length,
                  itemBuilder: (context, index) {
                    return buildDisplayBox(
                        context, index, _expandedTiles, size);
                  }),
/// code omitted

     
              child: TextField(
                controller: _textEditingController,
                onChanged: (value) {
                  _inputtedText = value;
                },
               
/// code omitted

You can user Dart's where search on any array and startsWith to look for matches that start with the term:

final myArray = ['abc', 'abd', 'acd', 'bca', 'abe'];
final results = myArray.where((e) => e.startsWith('ab'));
print (results);

The result will be:

(abc, abd, abe)

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