【问题标题】:Custom search through ArrayList for array names通过 ArrayList 自定义搜索数组名称
【发布时间】:2017-11-05 21:14:33
【问题描述】:

我正在尝试在我的自定义适配器中使用 getFilter 方法实现搜索过滤器。

通过列表进行搜索有两种模式。

  • 搜索项目的title
  • 搜索项目的genre[]

但我这里只说genre)。

下面的代码运行良好,但我需要的是在genre[] 中搜索的更自定义的方式。

我想要实现的是:(我想要的):

multi-keyword搜索,每个类别用,分隔。例如:genre1,genre2

(我做了什么)

当我输入 genre1,genre2 时,它会给出在类型中具有此序列的项目,它不会给出 genre1,genre3,genre2 或只是 genre1

你能帮忙吗?

getFilter:

@Override
public Filter getFilter() {
    Filter filter = new Filter() {
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            dataList = (List<ProductLocal>) results.values;
            notifyDataSetChanged();
        }
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            List<ProductLocal> filteredList = new ArrayList<>();
            constraint = constraint.toString().toLowerCase();
            for (int i = 0; i < dataListFilter.size(); i++) {
                ProductLocal dataNames = dataListFilter.get(i);

                String genreStr = "";
                for (String str : dataNames.getGenre()) {
                    genreStr += str + ",";
                }

                if (dataNames.getTitle().toLowerCase().startsWith(constraint.toString()) 
                 || genreStr.toLowerCase().contains(constraint.toString())) {
                    filteredList.add(dataNames);
                }
            }
            results.count = filteredList.size();
            results.values = filteredList;
            return results;
        }

    };
    return filter;
}

【问题讨论】:

  • @DastakWall 你想要一个 kotlin 答案吗?

标签: android search arraylist filter adapter


【解决方案1】:

如果满足这 2 个条件中的任何一个,您希望一首歌曲匹配更合适的歌曲:

  1. 歌曲的标题以整个搜索文本开头

  2. 歌曲的流派包含由,(逗号)分隔的部分搜索文本

如果是这样,请尝试以下搜索逻辑:

        @Override
        protected FilterResults performFiltering(CharSequence constraint)
        {
            FilterResults results = new FilterResults();
            List<ProductLocal> filteredList = new ArrayList<>();
            String searchText = constraint.toString().toLowerCase();
            String[] split = searchText.split(",");
            ArrayList<String> searchGenres = new ArrayList<String>(split.length);
            for (int i = 0; i < split.length; i++)
            {
                // remove spaces
                String trim = split[i].trim();
                // skip empty entries
                if (trim.length() > 0)
                    searchGenres.add(trim);
            }

            for (ProductLocal dataNames : dataListFilter)
            {
                // filter by title
                if (dataNames.getTitle().toLowerCase().startsWith(searchText))
                {
                    filteredList.add(dataNames);
                }
                else
                {
                    // filter by genres
                    // search for at least one common genre between song and search text
                    outer:
                    for (String songGenre : dataNames.getGenre())
                    {
                        for (String searchGenre : searchGenres)
                        {
                            if (songGenre.toLowerCase().contains(searchGenre))
                            {
                                filteredList.add(dataNames);
                                break outer;
                            }
                        }
                    }
                }
            }
            results.count = filteredList.size();
            results.values = filteredList;
            return results;
        }

这里唯一棘手的地方是break outer;。这是一种同时从两个for 循环中跳出的Java 语法。这里的想法是,如果我们在constraint 和一首歌曲之间找到了某种类型的匹配,我们将这首歌添加到filteredList,并且如果有更多匹配的类型,我们不想再次添加它。

附:如果按多种搜索类型过滤成为性能问题,您可以考虑构建单个 RegEx 以一次匹配所有搜索词或实现Aho–Corasick algorithm

【讨论】:

    【解决方案2】:

    请尝试拆分约束字符串,如下所示:

    @Override
    public Filter getFilter() {
        @SuppressWarnings("UnnecessaryLocalVariable")
        Filter filter = new Filter() {
            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                dataList = (List<ProductLocal>) results.values;
                notifyDataSetChanged();
            }
    
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults results = new FilterResults();
                List<ProductLocal> filteredList = new ArrayList<>();
    
                for (int i = 0; i < dataListFilter.size(); i++) {
                    ProductLocal dataNames = dataListFilter.get(i);
    
                    int count = 0;
                    String[] terms = constraint.toString().split(",");
    
                    for (int j = 0; j < terms.length; j++) {
    
                        String term = terms[j];
                        for (String str : dataNames.getGenre()) {
    
                            if (str.equals(term) || str.contains(term)) {
                                count++;
                                if (count == terms.length) {
                                    filteredList.add(dataNames);
                                }
                            }
                        }
                    }
                }
    
                results.count = filteredList.size();
                results.values = filteredList;
                return results;
            }
    
        };
        return filter;
    }
    

    【讨论】:

    • 不行,第一个关键字没问题,但是插入,列表后返回空
    • 请尝试编辑后的答案,如果可行,请告诉我。
    • 同理,但这次拆分后,列表将保留在第一个关键字上找到的项目,没有任何其他输入的功能
    • 能否请您添加更多代码,以便我自己尝试。
    • 我已经删除了我项目中所有不必要的文件并上传到这里(Android Studio):symphonyrecords.ir/apps/Project.zip
    【解决方案3】:

    您可以通过,分割搜索词

       String[] searmTearmArray= serachTerm.split(",");
    

    现在使用for 循环,您可以搜索这些字词。

    【讨论】:

    • 没有错误,但是当我在violin,light这样的序列中输入流派时,它会给出在流派中具有此序列的结果,它不会给出具有violin,electric,light的项目。
    猜你喜欢
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    • 2014-04-13
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多