1

I'm trying to write a program that checks if a string contains multiple words that must be occurred in a specific order the words are stored in Array of Strings

Here what I have reached so far

boolean Check = false;
Scanner S = new Scanner(System.in);            

System.out.println("What is your question?");
String input=S.nextLine();

String[] Words = {"pay","car"};

for (int i = 0; i <= Words.length -1  ; i++) {

    if (input.matches(".*\\b"+Words[i]+"\\b.*") && input.matches(".*\\b"+Words[1]+"\\b.*")) {
         Check = true;
    }
}
if (Check){
    System.out.println("30k Dollar");
} else{
    System.out.println("Wrong info! ");
}

Basically, what my code does is when the user input for example "how much should i pay for the car?" he will get an answer of "30k Dollar"

because the strings "pay" and "car" are both in my array of strings.

Case 2: if the user input " bla bla car bla bla pay"

he will get the same answer.

How can I prevent the program from giving the same answer for the 2 different questions?

also in my code I used Words[i] and Words[1] but when I got larger list of words this wont work, I tried using nested loop but it didn't work.

2
  • 1
    why do you want to prevent the same answer for both questions, i see they should be the same, both questions has multiple words from your array in the correct order, and when you say multiple do you mean more than two ? Commented Jan 3, 2018 at 16:22
  • I'm sorry i have edited case 2. even if the string "car came first then string "pay" it will show the same answer. and by multiple words i mean an array of more than 2 words how am i going to compare Commented Jan 3, 2018 at 16:34

3 Answers 3

1

You don't need to iterate over input words, just generate the full regex:

String[] words = {"pay","car"};
String regex = ".*\\b" + String.join("\\b.*\\b", words) + "\\b.*";

String test1= "how much should i pay for the car?";
System.out.println(test1.matches(regex)); // True

String test2 = "bla bla car bla bla pay";
System.out.println(test2.matches(regex)); // False
Sign up to request clarification or add additional context in comments.

6 Comments

This works great for the case of having only {"pay", "car"} in the array of words but when having more than 2 words user will have to input all of the words to get an answer?
This solution is indipendent from the number of words in the array, it will generate the proper regex for the matches. User will have to input the sentence exactly like before, doesn’t it look good for your case?
I edited my solution using a more compact regex generation
somehow my ide accepted String.join and it worked greatly thanks!
You need Java 8 in order to use String.join
|
0

I will assume you always look for words separated by spaces, so you can get the words separated using split

String inputWords[] = input.split(" ");

First thing we need to reduce the time complexity of checking if the word is in our array so we can fill the array in a set but since we care about the order we better use a map with key the word and value the index of that word in the array

Map<String,Integer> map = new HashMap<>();
String[] words = {"pay","car"};
for(int i =0; i< words.length; i++)
        map.put(words[i], i);

So now all you need is to iterate over your inputWords and check that all the words are there and you are not violating the order, this time complexity is O(n)

int lastFoundIndex = -1;
int numFound =0;
for(int i=0; i < inputWords.length; i++) {

if(map.get(inputWords[i]) != null ) {
    if(map.get(inputWords[i]) < lastFoundIndex)
       break;
     lastFoundIndex = map.get(inputWords[i]);
      numFound ++;
}
}
if(numFound  >= words.length) // this condition means we are allowing more than occurence without violating the order

     system.out.println("30k Dollar");

else 
     System.out.println("Wrong info! ");

2 Comments

if(map.get(inputWords[i]) < lastFoundIndex) here you are comparing an object to int that does not work
@Bashar no , map value is Integer, "we better use a map with key the word and value the index of that word in the array"
0

You could combine them into a single regex check. You're already matching any character before or after (with .*) so just basically concatenate your regex strings into a single check.

if (input.matches(".*\\b" + Words[0] + "\\b.*\\b" + Words[1] + "\\b.*"))

EDIT: response to "also in my code I used Words[i] and Words[1] but when I got larger list of words this wont work, I tried using nested loop but it didn't work."

You could just iterate over the input words to create the regex string. String regexPattern = ".*\\b" + String.Join("\\b.*\\b", Words) + "\\b.*";

EDIT2: here's my answer and edit combined w/ more context in the code:

String[] Words = {"pay","car"};
String regexPattern = ".*\\b" + String.Join("\\b.*\\b", Words) + "\\b.*";

if (input.matches(regexPattern)) {
  System.out.println("30k Dollar");
} else {
  System.out.println("Wrong info!");
}

EDIT3: Replaced Words.Join() with String.Join() cause I can Java w/o a compiler, real gud.

8 Comments

Thanks for the reply, But this will cause the same problem we used Word[1] (index 1 of the array) but later when i got more words in the array i cant keep using Words[1] , Words[2]. As i mentioned in the main topic i tried using nested loop but it didnt work well
Side note: Since you're just directly concatenating user input, the user could get strange behavior if they used any reserved regex characters. You might want to consider escaping the input before you concatenate it. Apparently, there's a Pattern.quote method that will do this: baeldung.com/java-regexp-escape-char
Updated answer w/ a snippet for accepting an arbitrary number of input words.
I didn't understand your edit? can you please explain?
You expressed the need to accept any number of words as input, so my edit just concatenates all of the input words with \\b.*\\b to make a single regex that matches the entire set of words in order. This way you don't need to hardcode the index of any word inputs.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.