Ezrou
Ezrou

Reputation: 438

Filter arraylist in java/android

Hello I need filter an ArrayList

I have a ArrayList with following items:

"Hello world" "Hello man" "Hello woman" "Goodbye world" "Goodbye man" "Goodbye woman"

then on TextBox I added a textchanged listener (Android).What i want is if I write "he wo" separated by space, it displays "Hello world" and "Hello woman".

I've been fighting with this about an hour and only I got is that if I write "he wo" I get the following items: "Hello world", "Hello man", "Hello woman", "Goodbye world". Here is the code

 et.addTextChangedListener(new TextWatcher()
    {
        public void afterTextChanged(Editable s)
        {
          // Abstract Method of TextWatcher Interface.
        }
        public void beforeTextChanged(CharSequence s,
        int start, int count, int after)
        {
        // Abstract Method of TextWatcher Interface.
        }
        public void onTextChanged(CharSequence s, int start, int before, int count)
        {
            //listabusClientes = new ArrayList<busCliente>();
            paraulesBuscar = s.toString().split(" "); //Array of string
            sortarray = new ArrayList<busCliente>(); //ArrayList of class busCliente
            sortarray.clear();

            for(int x = 0; x < paraulesBuscar.length; x++){
                sortarray.clear();
                for (int i = 0; i < listabusClientes.size(); i++)
                {
                    if ((listabusClientes.get(i).getNom().toUpperCase().indexOf(paraulesBuscar[x].toUpperCase()) != -1) || (listabusClientes.get(i).getCodiClient().toUpperCase().indexOf(paraulesBuscar[x].toUpperCase()) != -1))
                    {
                        sortarray.add(listabusClientes.get(i)); 
                    }
                }
            }
            lv.setAdapter(new ListViewAdapter(buscar_client.this,
                     R.layout.simple_list_item_1, sortarray));
        }
  });

Edited algorithm

paraulesBuscar = s.toString().split(" ");
                                    sortarray = new ArrayList<busCliente>();
                                    sortarray.clear();

                                    for(int x = 0; x < paraulesBuscar.length; x++){
                                        sortarray.clear();
                                        for (int i = 0; i < listabusClientes.size(); i++)
                                        {   
                                            String[] clientSplit = listabusClientes.get(i).getNom().split(" ");

                                            for(int cs = 0; cs < clientSplit.length; cs++){
                                                System.out.println(clientSplit[cs]);
                                                if (clientSplit[cs].toUpperCase().contains(paraulesBuscar[x].toUpperCase()))
                                                {
                                                    sortarray.add(listabusClientes.get(i)); 

                                                }
                                            }

                                        }
                                    }

Upvotes: 1

Views: 5647

Answers (2)

JB Nizet
JB Nizet

Reputation: 692231

Here's how I would do:

  1. split "he wo" into words, using String.split(), to get an array of prefixes ["he", "wo"]
  2. iterate on the items. For each item, split it into words, to get an array of words ["Hello", "World"]
  3. Check that the array of words has at least the same length as the array of prefixes. If not, the item is rejected
  4. Iterate through the indices of the prefixes. For each index, get the prefix and the word. Convert the word to lower-case. Check that it starts with the prefix. All these methods are available in the String class. If it doesn't start with the prefix, the item is rejected.

This should get you started. Make sure to implement this algorithm as a separate method, itself splitted into sub-methods doing just one thing.

EDIT:

here's the last part of the algorithm (steps 3 and 4):

/**
 * Tells if every prefix has a corresponding word and if every word, lower-cased, 
 * starts with the corresponding prefix.
 */
private boolean allPrefixesMatch(String[] prefixes, String[] words) {
    if (words.length < prefixes.length) {
        return false;
    }
    for (int i = 0; i < prefixes.length; i++) {
        String prefix = prefixes[i];
        String word = words[i];
        if (!word.toLowerCase().startsWith(prefix)) {
            return false;
        }
    }
    return true;
}

Upvotes: 1

FrancescoAzzola
FrancescoAzzola

Reputation: 2654

I suggest you to use a different approch to the problem. Create a custom adapter that extends ArrayAdapter and implements a filterable interface.

In your adapter create a private class that extends Filter; you have to override two methods:

protected FilterResults performFiltering(CharSequence constraint) {.. }

and

protected void publishResults(CharSequence constraint,
            FilterResults results) {..}

In the first one you set the filtering rule, in your case you can verify that a string is contanined in your items. In the second method you publish the results filtered calling notifyDataSetChanged();

You correctly added a changeTextListener but in the onTextChanged you call the filter to perform the filtering operation:

aAdpt.getFilter().filter(s.toString());

where aAdpt is your custom adapter. I hope i was clear. If you have some doubt you can refer to my post here.

Upvotes: 1

Related Questions