What steps are actually happening within the following two methods? I have a rough understanding of what the methods are to do, but I do not know how.
Method 1:
public String processDiscardedLetters(String name) {
return name.substring(0, 1)
+ name.substring(1).replaceAll("[aeihouwy]", "");
}
Method 2:
public String processEquivalentLetters(String name) {
name = name.replaceAll("[aeiou]", "a");
name = name.replaceAll("[cgjkqsxyz]", "c");
name = name.replaceAll("[bfpvw]", "b");
name = name.replaceAll("[dt]", "d");
name = name.replaceAll("[mn]", "m");
return name;
}
Example 1:
input: here are my
output: hr r m //replaced with '' (nothing)
Example 2 (first line):
input: cake is king xoxo
output: aaka as kang xoxo // replaced with 'a'
As you can see that the characters inside [] will be replaced with the character you write as 2nd parameter.
Both of the examples use regular expressions to transform input.
The bracket syntax [] is a character class, which means that any character inside it will match with a part of the input.
In particular, doing a string replace with [aeihouwy] will replace all occurrences of any of the letters with the replacement string.
Method 1: Preserves the first letter regardless of what it is, and removes all occurrences of of the of the characters aeihouwy for the rest of the string.
To be more specific, Method 1 is doing the following steps.
Separate the original string into two parts: The first character and the rest of the String. This uses the subString method with arguments 0 and 1 to pull out the first character, and argument 1 to extract the part of the string starting at the second character and ending at end of string.
Use replaceAll to eliminate any of the characters aeihouwy from the second half of the string.
Join the strings together again.
Method 2: For your first example
name = name.replaceAll("[aeiou]", "a"); // Replace of any of the letters `aeiou` with `a` whereever they occur.
String's substring(startIndex, endIndex) methods actually takes a string from a start index (inclusive) to the end index (exclusive) of the string array (A string is a CharSequence which is a "string array"). As you are aware, array counts starts from 0 to N - 1. A substring(startIndex) takes a string starting from index to the end of the string.
The replaceAll(String regularExpression, String replacement) method will replace a string based on the matched regular expression criteria. If a portion of a string matches a regular expression criteria, it gets replaced by a replacement string.
The regular expression in [ and ] are called character classes. These tell the regular expression engine to match only 1 out of those characters. So, if you have [aeihouwy], the words like grey will match since it identified gr[ey] and gr[e]y as well as gre[y]. So, any mentioned words will be replaced with a blank string "".
I hope this helps.
Related
My code is
public class Main
{
public static void main(String[] args)
{
String inputString = "#..#...##";
String[] abc = inputString.trim().split("#+");
for (int i = 0; i < abc.length; i++)
{
System.out.println(abc[i]);
}
System.out.println(abc.length);
}
}
The output abc is an array of length 3.
with abc[0] being an empty string. The other two elements in abc are .. and ...
If my inputString is "..##...". I don't get a empty string in the array returned by split function. The input String doesn't have trailing whitespace in both cases.
Can soemone explain me why do I get a extra space in the code shown above?
You don't get an extra space, you get the empty string (with length 0). It says so in the javadoc:
* <p> When there is a positive-width match at the beginning of this
* string then an empty leading substring is included at the beginning
* of the resulting array. A zero-width match at the beginning however
* never produces such empty leading substring
When you split by #+ and first character of input string is # then input is split at beginning itself and what you get is an empty string as first element of string. It is due to the fact that left hand side of first # is just anchor ^ which will give an empty string only in the resulting array.
From the Javadoc:
This method works as if by invoking the two-argument split method with the given expression and a limit argument of zero. Trailing empty strings are therefore not included in the resulting array.
And Javadoc:
If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded.
Whenever you say .split to a String, it splits the String n number of times that condition is met.
So when you say
String inputString = "#..#...##";
and your condition for spliting is # and since the value before the first occurrence of # is empty, abc[0] will hold empty. Therefore count of abc will return 3 because abc[0]=nothing(empty string), abc[1]=.. abc[2]=...
I have a method that converts all the first letters of the words in a sentence into uppercase.
public static String toTitleCase(String s)
{
String result = "";
String[] words = s.split(" ");
for (int i = 0; i < words.length; i++)
{
result += words[i].replace(words[i].charAt(0)+"", Character.toUpperCase(words[i].charAt(0))+"") + " ";
}
return result;
}
The problem is that the method converts each other letter in a word that is the same letter as the first to uppercase. For example, the string title comes out as TiTle
For the input this is a title this becomes the output This Is A TiTle
I've tried lots of things. A nested loop that checks every letter in each word, and if there is a recurrence, the second is ignored. I used counters, booleans, etc. Nothing works and I keep getting the same result.
What can I do? I only want the first letter in upper case.
Instead of using the replace() method, try replaceFirst().
result += words[i].replaceFirst(words[i].charAt(0)+"", Character.toUpperCase(words[i].charAt(0))+"") + " ";
Will output:
This Is A Title
The problem is that you are using replace method which replaces all occurrences of described character. To solve this problem you can either
use replaceFirst instead
take first letter,
create its uppercase version
concatenate it with rest of string which can be created with a little help of substring method.
since you are using replace(String, String) which uses regex you can add ^ before character you want to replace like replace("^a","A"). ^ means start of input so it will only replace a that is placed after start of input.
I would probably use second approach.
Also currently in each loop your code creates new StringBuilder with data stored in result, append new word to it, and reassigns result of output from toString().
This is infective approach. Instead you should create StringBuilder before loop that will represent your result and append new words created inside loop to it and after loop ends you can get its String version with toString() method.
Doing some Regex-Magic can simplify your task:
public static void main(String[] args) {
final String test = "this is a Test";
final StringBuffer buffer = new StringBuffer(test);
final Pattern patter = Pattern.compile("\\b(\\p{javaLowerCase})");
final Matcher matcher = patter.matcher(buffer);
while (matcher.find()) {
buffer.replace(matcher.start(), matcher.end(), matcher.group().toUpperCase());
}
System.out.println(buffer);
}
The expression \\b(\\p{javaLowerCase}) matches "The beginning of a word followed by a lower-case letter", while matcher.group() is equal to whats inside the () in the part that matches. Example: Applying on "test" matches on "t", so start is 0, end is 1 and group is "t". This can easily run through even a huge amount of text and replace all those letters that need replacement.
In addition: it is always a good idea to use a StringBuffer (or similar) for String manipulation, because each String in Java is unique. That is if you do something like result += stringPart you actually create a new String (equal to result + stringPart) each time this is called. So if you do this with like 10 parts, you will in the end have at least 10 different Strings in memory, while you only need one, which is the final one.
StringBuffer instead uses something like char[] to ensure that if you change only a single character no extra memory needs to be allocated.
Note that a patter only need to be compiled once, so you can keep that as a class variable somewhere.
I am trying to create a String[] which contains only words that comprise of certain characters. For example I have a dictionary containing a number of words like so:
arm
army
art
as
at
attack
attempt
attention
attraction
authority
automatic
awake
baby
back
bad
bag
balance
I want to narrow the list down so that it only contains words with the characters a, b and g. Therefore the list should only contain the word 'bag' in this example.
Currently I am trying to do this using regexes but having never used them before I can't seem to get it to work.
Here is my code:
public class LetterJugglingMain {
public static void main(String[] args) {
String dictFile = "/Users/simonrhillary/Desktop/Dictionary(3).txt";
fileReader fr = new fileReader();
fr.openFile(dictFile);
String[] dictionary = fr.fileToArray();
String regx = "able";
String[] newDict = createListOfValidWords(dictionary, regx);
printArray(newDict);
}
public static String[] createListOfValidWords(String[] d, String regex){
List<String> narrowed = new ArrayList<String>();
for(int i = 0; i<d.length; i++){
if(d[i].matches(regex)){
narrowed.add(d[i]);
System.out.println("added " + d[i]);
}
}
String[] narrowArray = narrowed.toArray(new String[0]);
return narrowArray;
}
however the array returned is always empty unless the String regex is the exact word! Any ideas? I can post more code if needed...I think I must be trying to initialise the regex wrong.
The narrowed down list must contain ONLY the characters from the regex.
Frankly, I'm not an expert in regexes, but I don't think it's the best tool to do what you want. I would use a method like the following:
public boolean containsAll(String s, Set<Character> chars) {
Set<Character> copy = new HashSet<Character>();
for (int i = 0; i < s.length() && copy.size() < chars.size(); i++) {
char c = s.charAt(i);
if (chars.contains(c)) {
copy.add(c);
}
}
return copy.size() == chars.size();
}
The regex able will match only the string "able". However, if you want a regular expression to match either character of a, b, l or e, the regex you're looking for is [able] (in brackets). If you want words containing several such characters, add a + for repeating the pattern: [able]+.
The OP wants words that contain every character. Not just one of them.
And other characters are not a problem.
If this is the case, I think the simiplest way would be to loop through the entire string, character by character, and check to see if it contains all of the characters you want. Keep flags to check and see if every character has been found.
If this isn't the case.... :
Try using the regex:
^[able]+$
Here's what it does:
^ matches the beginning of the string and $ matches the end of the string. This makes sure that you're not getting a partial match.
[able] matches the characters you want the string to consist of, in this case a, b, l, and e. + Makes sure that there are 1 or more of these characters in the string.
Note: This regex will match a string that contains these 4 letters. For example, it will match:
able, albe, aeble, aaaabbblllleeee
and will not match
qable, treatable, and abled.
A sample regex that filters out words that contains at least one occurrence of all characters in a set. This will match any English word (case-insensitive) that contains at least one occurrence of all the characters a, b, g:
(?i)(?=.*a)(?=.*b)(?=.*g)[a-z]+
Example of strings that match would be bag, baggy, grab.
Example of strings that don't match would be big, argument, nothing.
The (?i) means turns on case-insensitive flag.
You need to append as many (?=.*<character>) as the number of characters in the set, for each of the characters.
I assume a word only contains English alphabet, so I specify [a-z]. Specify more if you need space, hyphen, etc.
I assume matches(String regex) method in String class, so I omitted the ^ and $.
The performance may be bad, since in the worst case (the characters are found at the end of the words), I think that the regex engine may go through the string for around n times where n is the number of characters in the set. It may not be an actual concern at all, since the words are very short, but if it turns out that this is a bottleneck, you may consider doing simple looping.
Alright so here is my problem. Basically I have a string with 4 words in it, with each word seperated by a #. What I need to do is use the substring method to extract each word and print it out. I am having trouble figuring out the parameters for it though. I can always get the first one right, but the following ones generally have problems.
Here is the first piece of the code:
word = format.substring( 0 , format.indexOf('#') );
Now from what I understand this basically means start at the beginning of the string, and end right before the #. So using the same logic, I tried to extract the second word like so:
wordTwo = format.substring ( wordlength + 1 , format.indexOf('#') );
//The plus one so I don't start at the #.
But with this I continually get errors saying it doesn't exist. I figured that the compiler was trying to read the first # before the second word, so I rewrote it like so:
wordTwo = format.substring (wordlength + 1, 1 + wordLength + format.indexOf('#') );
And with this it just completely screws it up, either not printing the second word or not stopping in the right place. If I could get any help on the formatting of this, it would be greatly appreciated. Since this is for a class, I am limited to using very basic methods such as indexOf, length, substring etc. so if you could refrain from using anything to complex that would be amazing!
If you have to use substring then you need to use the variant of indexOf that takes a start. This means you can start look for the second # by starting the search after the first one. I.e.
wordTwo = format.substring ( wordlength + 1 , format.indexOf('#', wordlength + 1 ) );
There are however much better ways of splitting a string on a delimiter like this. You can use a StringTokenizer. This is designed for splitting strings like this. Basically:
StringTokenizer tok = new StringTokenizer(format, "#");
String word = tok.nextToken();
String word2 = tok.nextToken();
String word3 = tok.nextToken();
Or you can use the String.split method which is designed for splitting strings. e.g.
String[] parts = String.split("#");
String word = parts[0];
String word2 = parts[1];
String word3 = parts[2];
You can go with split() for this kind of formatting strings.
For instance if you have string like,
String text = "Word1#Word2#Word3#Word4";
You can use delimiter as,
String delimiter = "#";
Then create an string array like,
String[] temp;
For splitting string,
temp = text.split(delimiter);
You can get words like this,
temp[0] = "Word1";
temp[1] = "Word2";
temp[2] = "Word3";
temp[3] = "Word4";
Use split() method to do this with "#" as the delimiter
String s = "hi#vivek#is#good";
String temp = new String();
String[] arr = s.split("#");
for(String x : arr){
temp = temp + x;
}
Or if you want to exact each word... you have it already in arr
arr[0] ---> First Word
arr[1] ---> Second Word
arr[2] ---> Third Word
I suggest that you've a look at the Javadoc for String before you proceed further.
Since this is your homework, I'll give you a couple of hints and maybe you can solve it yourself:
The format for subString is public void subString(int beginIndex, int endIndex). As per the javadoc for this method:
Returns a new string that is a substring of this string. The substring
begins at the specified beginIndex and extends to the character at
index endIndex - 1. Thus the length of the substring is
endIndex-beginIndex.
Note that if you've to use this method, understand that you'll have to shift your beginIndex and endIndex each time because in your situation, you'll have multiple words that are separated by #.
However if you look closely, there's another method in String class that might be helpful to you. That's the public String[] split(String regex) method. The javadoc for this one states:
Splits this string around matches of the given regular expression.
This method works as if by invoking the two-argument split method with
the given expression and a limit argument of zero. Trailing empty
strings are therefore not included in the resulting array.
The split() method looks pretty interesting for your case. You can split your String with the delimiter that you have as the parameter to this method, get the String array and work with that.
Hope this helps you to understand your problem and get started towards a solution :)
Since this is a home work, it may be better to have try to write it your self. But I will give a clue.
Clue:
The indexOf method has another overload: int indexOf(int chr,
int fromIndex) which find the first character chr in the string
from the fromIndex.
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html
From this clue, the program will look something like this:
Find the index of the first '#' from the start of the string.
Extract the word from 0th character to that index.
Find the index of the first '#' from the character AFTER the first '#'.
Extract the word from the first '#' that index.
... Just do it until you get 4 words or the string ends.
Hope this helps.
I don't know why you're forced to use String#substring, but as others have mentioned, it seems like the wrong method for the kind of functionality you need.
String#split(String regex) is what you would use for such a problem, or, if your input sequence is something you don't control, I would suggest you look at the overloaded method String#split(String regex, int limit); this way you can impose a limit on the amount of matches you make, controlling your resulting array.
I have strings with this format: "a,b, c,d" and this format: "a(b,c,d)"
I want to split on ',' or ', ' but I want to terminate splitting when I encounter the '(' in the second format.
This is what I had before I started hacking.
String [] stringArray = string.split(", |,");
The array of the first format would contain: 'a', 'b', 'c', 'd'
The array of the second format would conaint 'a(b,c,d)'
Example:
String string1 = "ab,cd, de";
String string2 = "ab(de,ef);
String [] array1 = string1.split(...);
String [] array2 = string2.split(...);
array1 result: ["ab" "cd" "de"]
array2 result: ["ab(de,ef)"]
The number of characters between the commas are not limited. I hope this is more clear.
Thanks.
If you know the parentheses are always properly balanced and they'll never be nested inside other parens, this will work:
String[] result = source.split(",\\s*(?![^()]*\\))");
If the lookahead finds a ) without seeing a ( first, it must be inside a pair of parens. Given this string:
"ab,cd, de,ef(gh,ij), kl,mn"
...result will be:
["ab", "cd", "de", "ef(gh,ij)", "kl", "mn"]
I think what you could need is a negative lookbehind; according to the doc, Java regex are like (more or less) Perl regex; but variable length lookbehind is not implemented in Perl, so that (?<!\(.*),\s* won't work (it would match comma followed by any number of spaces or no space, and not preceded by a ( followed by anything, i.e. would match comma only if not preceded by a ().
I believe the easiest thing is to split on the first ( occurrence (you can avoid regex to do so) and treat the two resulting segments differently, splitting the first on , and adding to the final array the second (prepended with the maybe lost ().
EDIT
since "a(b,d)" should give "a(b,d)", you must append whatever comes after ( (included) to the last splited string from the "first" segment. However, the concept is as written before.
Use the indexOf() method.
Initially, check if a string has a "(".
index = string.indexOf('(');
if(index ==-1) // it means there is no '('
{
string.split(...);
}
else
{
subString = string.subString(0,index); // the part of the string before the '('
// now do the following-
// 1. proceed with split on substring
// array1 = substring.split(...)
// 2. Create a new array, insert the elements of array1 in it,
// followed by the remaining part of the string
// array2 = combine(array1, string.subString(index+1)); // <-- you will need to write this method
}