4

I am looking for a regular expression that can help me search a list of email strings such that say, if I have an arraylist with a couple of emails listed such that : firstname.lastname@company.com , firstname1.lastname1@company.com I would like to search through them such that in my filter if I add rst name1 ,it will display firstname1.lastname1@company.com , I have the filter code in place and it searches thru every matched letter. however I would like to modify it and make it search the characters before or after the dot "." with regular expressions. How do I go about it? Here's my filter search code :

protected synchronized FilterResults performFiltering(CharSequence constraint) {

                FilterResults results = new FilterResults();

                if (constraint != null && constraint.length() > 0) {

                    ArrayList<Integer> filterList = new ArrayList<>();

                    int iCnt = listItemsHolder.Names.size();
                    for (int i = 0; i < iCnt; i++) {
                        if(listItemsHolder.Types.get(i).toString().indexOf("HEADER_")>-1){
                            continue;
                        }
                        if (listItemsHolder.Names.get(i).toLowerCase().contains(constraint.toString().toLowerCase())) {
                            if(filterList.contains(i))
                                continue;

                            filterList.add(i);

                        }

                    }

                    results.count = filterList.size();

                    results.values = filterList;
                }else {

                    results.count = listItemsHolder.Names.size();

                    ArrayList<Integer> tList = new ArrayList<>();
                    for(int i=0;i<results.count;i++){
                        tList.add(i);
                    }

                    results.values = tList;

                }

                return results;
            }


            //Invoked in the UI thread to publish the filtering results in the user interface.
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                ArrayList<Integer> resultsList = (ArrayList<Integer>)results.values;
                if(resultsList != null) {
                    m_filterList = resultsList;
                }
                notifyDataSetChanged();
            }
        }

where

class ListItemsHolder {

public ArrayList<String>        Names;
}

contains all the necessary names in the format firstname.lastname@company.com

Amar
  • 420
  • 3
  • 14
  • just to add a note: to be more clear, If I am looking for my email justice.bauer@email.com , i go about searching it like "j bau" it will return my email from the list. it will the space after the first name. even if i add ju.bau it will bring up my email and ignore the dot in between, just search by the letters before and after the dot –  Oct 22 '15 at 19:05
  • 2
    You could probably remove all the details of populating and list and focus on the filtering. You should also say exactly what you want to happen and exactly what your code already accomplishes, it is not completely clear. – SilverCorvus Oct 24 '15 at 23:57
  • currently I am able to search with letters, say I have firstname.lastname@company.com and search for letter t, it shows that email, then i search for " first lastname" with a space in between it doesnt show anything. i would like to see firstname.lastname@company.com to show up even when theres a space in between searched firstname and lastname as long as one or more syllables separated by the dot match –  Oct 25 '15 at 00:16

3 Answers3

1

If I understood correctly, you can replace the space with .*\..*

For example, an input of jer ld will become jer.*\..*ld and will match "jerry.seinfeld" -

Note it will NOT match "jerald.melberg" - since the 'jer' and 'ld' are not separated by '.' - is this what you want?

Explanation for the regex - in words "zero or more characters (.*), followed by dot (\.) , followed by zero or more characters (.*)"

In your code:

// just once before the loop:
String regex = constraint.replaceAll("[ .]+", ".*\..*")+".*@";
Pattern pattern = Pattern.compile(regex, CASE_INSENSITIVE);

// then in the loop,
// instead of:
// if (listItemsHolder.Names.get(i).toLowerCase().contains(constraint.toString().toLowerCase())) {
// do instead:
if (pattern.matcher(listItemsHolder.Names.get(i)).matches()) { ...
Iftah
  • 9,512
  • 2
  • 33
  • 45
0

Assuming that you're going to pass max two parameters.

I'll do an example supposing you submitted 'rst name1' and want to find 'firstname1.lastname1@company.com'. The Regex that you want is:

.*rst.*\..*name1.*\@

Explanation:

regex:   .*   rst   .*    \.  .*   ast   .*     \@
matches: fi   rst   name  .   l    ast   name   @

If there's just one constraint, 'rst', then you want:

.*rst.*\@

Pseudo code (not tested):

arrayOfConstraintParts = constraint.split(" ");  // explode the constraint into an array of constraints
if (arrayOfConstraintParts.length >= 2) {        // If you have at least 2 constraints
    regex = ".*" . arrayOfConstraintParts[0] . ".*\..*" . arrayOfConstraintParts[1] . ".*\@";
} else {                                         // If you have only 1 constraint
    regex = ".*" . arrayOfConstraintParts[0] . ".*\@";
}

I find this useful: https://regex101.com/

Damian
  • 34
  • 4
0

You didn't explicitly define how sensitive this filter should be, so let's say we want to filter every email with given string (if there is char sequence without space) or every email containing every part of string (with space as delimiter between parts).

WITHOUT REGEX:

you could for example try with something like:

boolean itFit; //additional variable
List<String> results;

if (constraint != null && constraint.length() > 0) {

    ArrayList<Integer> filterList = new ArrayList<>();

    int iCnt = listItemsHolder.Names.size();
    for (int i = 0; i < iCnt; i++) {
        itFit = true;     // default state of itFit is ture,
        if(listItemsHolder.Types.get(i).toString().indexOf("HEADER_")>-1){
            continue;
        }
        for(String con : constraint.toString().split("\\s")) {   // constraint as string is splitted with space (\s) as delimiter, the result is an array with at least one element (if there is no space)
            if (!listItemsHolder.Names.get(i).toLowerCase().contains(con.toLowerCase())) {
                itFit = false;    // if email doesn't contains any part of splitted constraint, the itFit value is changed to false 
            }

        }
        if(itFit && !filterList.contains(i)){   // if itFit is true, add element to list
            filterList.add(listItemsHolder.Names.get(i));
        }
    }

    results = filterList;
}

I tested this code with List<String> so there coulde be some little differences with your code, but it works fo me. Also it is just example, it could be easily implemented in another way. I just did't want to change your code too much.

WITH REGEX:

With addition of small method to create regex pattern:

public String getRegEx(CharSequence elements){
    String result = "(?i).*";
    for(String element : elements.toString().split("\\s")){
        result += element + ".*";
    }
    result += "@.*";  // it will return String like "(?i).*j.*bau.*"
    return result;
}

you can change:

if (listItemsHolder.Names.get(i).toLowerCase().contains(constraint.toString().toLowerCase())) {

into:

if (listItemsHolder.Names.get(i).matches(getRegEx(constraint))) {

However this regex will not contain a \. part, so it will not be obligatory, and with input j bau it will match jeff.bauser@company.com, and jerbauman@comp.com. But it could be changed easily, and as I wrote above, it is not explicitly defined how it should filter names, also I am not sure how many parts could such email contain, and what kind of input you want to allow. With this method, you can also type f name l name and it will find firstname1.lastname1@company.com.

Community
  • 1
  • 1
m.cekiera
  • 5,365
  • 5
  • 21
  • 35
  • the regex one seems to be better, but I wonder how do i modify it if I have to search something with company name say j bau comp or say i work for abc then i will search for " ju ba bc" ,how do i modify the regex to work for that –  Oct 26 '15 at 14:07
  • got it . removed the @ from your regex exp. works fine! thanks –  Oct 26 '15 at 15:50