I have two lists of words,
A: pit pot spate slaptwo respite,
B: pt Pot peat part
I have to create a regex Pattern that returns true for everything in column A and false for everything in column B. I think there is something I'm fundamentally missunderstanding about regex, because everything I come up with ends up with having one extra false where I don't want it. Mainly I can't seen to figure out how to disallow two vowels next to each other.
Here's what I have:
public static void main(String[] args){
String[] check = {"pit","spot","spate","slaptwo","respite","pt","Pot","peat","part"};
Pattern p = Pattern.compile("([psr][^t(ea)][^r])\\w*");
ArrayList<Matcher> M = new ArrayList<Matcher>();
for (int i = 0; i < check.length; i++) {
M.add(p.matcher(check[i]));
}
for (int j = 0; j < M.size(); j++){
System.out.println("Return Value:" +check[j] + "\t"+ M.get(j).matches());
}
}
I understand now that (ea) is not being read as one thing so it causes respite to be false when I don't want it to, everything else returns the correct value. As I said before I need to know how to disallow two vowels being next to each other. Or if I am just missing something fundamental here?
You cannot use grouping constructs inside of a character class.
To disallow "ea" you can use Negative Lookahead here.
[psr](?!ea)[^t][^r]\\w*
Live Demo
Related
I am new to Java and am trying to make a program that will take a string 'names' and replace the names of the people mentioned in that string with a nickname from another string 'replacement'. For instance, "John and Robert were on the way to meet Elizabeth" should return "Joe and Bob were on the way to meet Liz".
My issue is that whenever I run my program, I get multiple sentences back with only one name replaced in each (I'm guessing it is creating a new string each time). Is there a way to avoid this and have it all printed in one sentence? Could I use regex on 'replacement' somehow to fix it?
public static string namereplacer(String names, String replacement) {
String[] toreplace = replacement.split("\t|\n");
for (int i = 0; i <= toreplace.length/2; i++) {
if (i % 2 == 0) { //take even values
fixed; += names.replaceAll(toreplace[i+1],toreplace[i]);
}
}
return fixed;
}
public static void main (String[] args) {
namereplacer("John and Robert were on the way to meet Elizabeth", "John\tJoe\nRobert\tBob\nElizabeth\tLiz");
}
I couldn't run the code you have submitted because the variable fixed isn't declared and i suspect the line
fixed; += names.replaceAll(toreplace[i+1],toreplace[i]);
is supposed to be
fixed += names.replaceAll(toreplace[i+1],toreplace[i]);
because that would somewhat explain why you are getting multiple sentences, since you are replacing things multiple times and adding the result to fixed.
That being said I have noticed that when you are replacing the names with
names.replaceAll(toreplace[i+1],toreplace[i]); you should be doing
names.replaceAll(toreplace[i],toreplace[i+1]); since you would like to replace John for Joe, Robert for Bob and Elizabeth for Liz, not the other way around (Joe for John). Basically you want to replace the "even" with the "odd" so if you are selecting the even values of i you you like to replace those with i+1.
Also when iterating the array in the for loop with
for (int i = 0; i <= toreplace.length/2; i++)
you should be doing
for (int i = 0; i <= toreplace.length; i++)
because you want all the "evens" not just half of them, i think you might have switched up yourself a bit here with the evens logic and replacing half...
So to make your code work like you intend to you should replace the following lines:
for (int i = 0; i <= toreplace.length/2; i++) for
for (int i = 0; i <= toreplace.length; i++)
fixed; += names.replaceAll(toreplace[i+1],toreplace[i]); for
fixed = fixed.replaceAll(toreplace[i+1],toreplace[i]);
and also define the variable fixed beforehand Sting fixed = names; so that it has the same value as names.
Furthermore you can also improve your code a little bit:
A for is constituted by three statements for(statement1; statement2; stament3)
statement1 is executed a single time before the code block (what's inside the for)
statement2 defines the condition for executing the code block, the for will run while this statement is true
statement3 is executed everytime after the code block has been executed by the for loop
Generaly you will find and write foor loops like for(i=0; i!=foo; i++) where statement1 is used for variable initialization, statement2 for condition and statement3 for increment, but that doens't mean it is all you can do with it, in reality you can write whatever you want/need in those statements.
In you case you have
for (int i = 0; i <= toreplace.length/2; i++) {
if (i % 2 == 0) { //take even values
fixed; += names.replaceAll(toreplace[i+1],toreplace[i]);
}
}
This means you are iterating over the toreplace array, taking the "evens" and replacing them with the "odds" on the fixed string, however inside the for loop you are selecting only half of the iterations you are making with if (i % 2 == 0) and you don't really need to do that since you can just choose to iterate by 2 instead of iterating all of them and only selecting half of them to do the replacement.
To do this you simply declare for (int i = 0; i != toreplace.length; i+=2) or the long way i=i+2 if you prefer, and you no longer need the if statement because you know you will be iteraing over all the even numbers.
Hope this helped you in some way.
Change the method namereplacer to this
public static String namereplacer(String names, String replacement) {
String[] toreplace = replacement.split("\n");
for(String str: toreplace){
String [] keyValue = str.split("\t");
if(keyValue.length != 2)
continue;
names = names.replaceAll(keyValue[0], keyValue[1]);
}
return names;
}
I am stuck on a problem for a very long time which requires me to compute a terms x terms matrix. So, I have 2 arrays which is keywords and sentences as below:
String[] Keywords = {"Human", "Machine", "Interface", "Application" };
String[] Sentence = {"Human is Machine", "Interface of Robot", "Application on Human"};
Next, I have to tabulate them as shown in the figure below.
Logic:
We put a 0 if the row and column is of the same keyword.
In Human(row) x Machine(column) space, we put 1 because these two
words appear in the same sentence once (that is the first sentence
in the array).
In Human(row) x Interface(column), we put 0 because this two words
doesn't exist together in neither of the sentences.
The search is non case sensitive.
And proceed to the next column and then next row.
This is what I've attempted but somehow something is wrong.
public class Test {
public static int [][] matrix;
public static void main(String[] args) throws Exception {
String[] Keywords = {"Human", "Machine", "Interface", "Application" };
String[] Sentence = {"Human is Machine", "Interface of Robot", "Application on Human"};
int [][] matrix = new int[Keywords.length][Keywords.length]; //initialize matrix
System.out.println(Arrays.toString(Keywords));
System.out.println("\n"+ Arrays.toString(Sentence));
for (int i=0;i<Keywords.length;i++)
{
int count = 0;
for (int q=1;q<Sentence.length;q++)
{
if (Keywords[i].contains(Sentence[q]))
{
matrix[i][q] = count++;
}
}
}
System.out.println(Arrays.deepToString(matrix));
}
}
Any help is appreciated. Thanks!
There are some logical errors in your forloop.
With if (Keywords[i].contains(Sentence[q])) you are checking whether the keyword contains the sentence and not whether the opposite holds.
Another thing is that your matrix is based on the Keywords yet you are using the Sentence iterator to indicate the line.
Correct code would be
for (int i=0;i<Keywords.length-1;i++){
for(int j = i+1; j < Keywords.length; j++){
int count = 0;
for (int q=0;q<Sentence.length;q++){
if(Sentence[q].contains(Keywords[i]) && Sentence[q].contains(Keywords[j])){
count++;
}
}
matrix[i][j] = count;
matrix[j][i] = count;
}
}
This will output your example matrix.
There are several mistakes to your program:
if (Keywords[i].contains(Sentence[q]))
this condition checks whether a sentence is contained in a keyword. You want to check the opposite.
matrix[i][q] = count++;
Why do you use this? You want to set the value of the cell to 1, if you find a match. Simply set the value to 1 instead of using a complicated expression that doesn't even work:
matrix[i][q] = 1;
In general:
Whatever IDE you use should provide a debugger. Learn to use it; there's no way to avoid this anyways, if you want to write working code on a larger scale.
Is there a way to check if a substring contains an entire WORD, and not a substring.
Envision the following scenario:
public class Test {
public static void main(String[] args) {
String[] text = {"this is a", "banana"};
String search = "a";
int counter = 0;
for(int i = 0; i < text.length; i++) {
if(text[i].toLowerCase().contains(search)) {
counter++;
}
}
System.out.println("Counter was " + counter);
}
}
This evaluates to
Counter was 2
Which is not what I'm looking for, as there is only one instance of the word 'a' in the array.
The way I read it is as follows:
The if-test finds an 'a' in text[0], the 'a' corresponding to "this is [a]". However, it also finds occurrences of 'a' in "banana", and thus increments the counter.
How can I solve this to only include the WORD 'a', and not substrings containing a?
Thanks!
You could use a regex, using Pattern.quote to escape out any special characters.
String regex = ".*\\b" + Pattern.quote(search) + "\\b.*"; // \b is a word boundary
int counter = 0;
for(int i = 0; i < text.length; i++) {
if(text[i].toLowerCase().matches(regex)) {
counter++;
}
}
Note this will also find "a" in "this is a; pause" or "Looking for an a?" where a doesn't have a space after it.
Could try this way:
for(int i = 0; i < text.length; i++) {
String[] words = text[i].split("\\s+");
for (String word : words)
if(word.equalsIgnoreCase(search)) {
counter++;
break;
}
}
If the words are separated by a space, then you can do:
if((" "+text[i].toLowerCase()+" ").contains(" "+search+" "))
{
...
}
This adds two spaces to the original String.
eg: "this is a" becomes " this is a ".
Then it searches for the word, with the flanking spaces.
eg: It searches for " a " when search is "a"
Arrays.asList("this is a banana".split(" ")).stream().filter((s) -> s.equals("a")).count();
Of course, as others have written, you can start playing around with all kinds of pattern to match "words" out of "text".
But the thing is: depending on the underlying problem you have to solve, this might (by far) not good enough. Meaning: are you facing the problem of finding some pattern in some string ... or is it really, that you want to interpret that text in the "human language" sense? You know, when somebody writes down text, there might be subtle typos, strange characters; all kind of stuff that make it hard to really "find" a certain word in that text. Unless you dive into the "language processing" aspect of things.
Long story short: if your job is "locate certain patterns in strings"; then all the other answers will do. But if your requirement goes beyond that, like "some human will be using your application to 'search' huge data sets"; then you better stop now; and consider turning to full-text enabled search engines like ElasticSearch or Solr.
I have an array that prints out the number with a comma attached but for the last iteration, I don't want there to be a comma attached to the last number. Is there a way that I can create an if statement that only applies to the last iteration? Its java.
There are often much better ways depending on your language.
In Java 8 you should be able to use String.join(", ", listOfItems)
There are a few other Join methods that work the same way in older versions of Java but I always have trouble finding them.
In Groovy and Ruby I believe all the collections have join methods that work like this:
assert "this is a test".split(" ").join(", ") == "this, is, a, test"
Just print the , before the item and don't do it for the first one. You didn't mention the language but Java/C/C#/Javascript solution would be something like:
for (int x = 0; x < ListSize; x++)
{
if (i > 0)
{
print ",";
}
print list[i];
}
you can check on the last item of the array in most languages. Though, it seems your issue is probably a design and not syntax issue.
Any how, here is an example in javascript
var ar = ['1', '2', '3', '4', '5'];
for (var i = 0; i < ar.length; i++) {
if (i == ar.length - 1) {
console.log(ar[i]);
} else {
console.log(ar[i] + ',');
}
}
create a string by iterating and appending comma, and then do substring. "1,2,3,".substring(0,L-1) where L is length.
So, I'm in need of help on my homework assignment. Here's the question:
Write a static method, getBigWords, that gets a String parameter and returns an array whose elements are the words in the parameter that contain more than 5 letters. (A word is defined as a contiguous sequence of letters.) So, given a String like "There are 87,000,000 people in Canada", getBigWords would return an array of two elements, "people" and "Canada".
What I have so far:
public static getBigWords(String sentence)
{
String[] a = new String;
String[] split = sentence.split("\\s");
for(int i = 0; i < split.length; i++)
{
if(split[i].length => 5)
{
a.add(split[i]);
}
}
return a;
}
I don't want an answer, just a means to guide me in the right direction. I'm a novice at programming, so it's difficult for me to figure out what exactly I'm doing wrong.
EDIT:
I've now modified my method to:
public static String[] getBigWords(String sentence)
{
ArrayList<String> result = new ArrayList<String>();
String[] split = sentence.split("\\s+");
for(int i = 0; i < split.length; i++)
{
if(split[i].length() > 5)
{
if(split[i].matches("[a-zA-Z]+"))
{
result.add(split[i]);
}
}
}
return result.toArray(new String[0]);
}
It prints out the results I want, but the online software I use to turn in the assignment, still says I'm doing something wrong. More specifically, it states:
Edith de Stance states:
⇒ You might want to use: +=
⇒ You might want to use: ==
⇒ You might want to use: +
not really sure what that means....
The main problem is that you can't have an array that makes itself bigger as you add elements.
You have 2 options:
ArrayList (basically a variable-length array).
Make an array guaranteed to be bigger.
Also, some notes:
The definition of an array needs to look like:
int size = ...; // V- note the square brackets here
String[] a = new String[size];
Arrays don't have an add method, you need to keep track of the index yourself.
You're currently only splitting on spaces, so 87,000,000 will also match. You could validate the string manually to ensure it consists of only letters.
It's >=, not =>.
I believe the function needs to return an array:
public static String[] getBigWords(String sentence)
It actually needs to return something:
return result.toArray(new String[0]);
rather than
return null;
The "You might want to use" suggestions points to that you might have to process the array character by character.
First, try and print out all the elements in your split array. Remember, you do only want you look at words. So, examine if this is the case by printing out each element of the split array inside your for loop. (I'm suspecting you will get a false positive at the moment)
Also, you need to revisit your books on arrays in Java. You can not dynamically add elements to an array. So, you will need a different data structure to be able to use an add() method. An ArrayList of Strings would help you here.
split your string on bases of white space, it will return an array. You can check the length of each word by iterating on that array.
you can split string though this way myString.split("\\s+");
Try this...
public static String[] getBigWords(String sentence)
{
java.util.ArrayList<String> result = new java.util.ArrayList<String>();
String[] split = sentence.split("\\s+");
for(int i = 0; i < split.length; i++)
{
if(split[i].length() > 5)
{
if(split[i].matches("[a-zA-Z]+"))
{
result.add(split[i]);
}
if (split[i].matches("[a-zA-Z]+,"))
{
String temp = "";
for(int j = 0; j < split[i].length(); j++)
{
if((split[i].charAt(j))!=((char)','))
{
temp += split[i].charAt(j);
//System.out.print(split[i].charAt(j) + "|");
}
}
result.add(temp);
}
}
}
return result.toArray(new String[0]);
}
Whet you have done is correct but you can't you add method in array. You should set like a[position]= spilt[i]; if you want to ignore number then check by Float.isNumber() method.
Your logic is valid, but you have some syntax issues. If you are not using an IDE like Eclipse that shows you syntax errors, try commenting out lines to pinpoint which ones are syntactically incorrect. I want to also tell you that once an array is created its length cannot change. Hopefully that sets you off in the right directions.
Apart from syntax errors at String array declaration should be like new String[n]
and add method will not be there in Array hence you should use like
a[i] = split[i];
You need to add another condition along with length condition to check that the given word have all letters this can be done in 2 ways
first way is to use Character.isLetter() method and second way is create regular expression
to check string have only letter. google it for regular expression and use matcher to match like the below
Pattern pattern=Pattern.compile();
Matcher matcher=pattern.matcher();
Final point is use another counter (let say j=0) to store output values and increment this counter as and when you store string in the array.
a[j++] = split[i];
I would use a string tokenizer (string tokenizer class in java)
Iterate through each entry and if the string length is more than 4 (or whatever you need) add to the array you are returning.
You said no code, so... (This is like 5 lines of code)