Java: Contains() method - java

Trying to implement contains() method without using built-in method contains().
Here is my code:
public static boolean containsCS(String str, CharSequence cs) {
//char[] chs = str.toCharArray();
boolean result = false;
int i=0;
while(i<str.length()) {
int j=0;
while(j<cs.length()) {
if(NEED TO CHECK IF THERE IS AN INDEX OUT OF BOUNDS EXCEPTION) {
result = false;
break;
}
if(str.charAt(i+j)==cs.charAt(j)) {
result|=true; //result = false or true ->>>>> which is true.
j++;
} else {
result = false;
break;
}
}
i++;
}
return false;
}
Let's say:
String str = "llpll"
Charsequence cs = "llo"
I want to make sure this method works properly in the above case where the Charsequence has one or more char to check but the String runs out length. How should I write the first if statement?

if (i+cs.length() > str.length()){
OUT OF BOUNDS
}

Well if it were me first thing I'd check is that the length of my char sequence was <= to the length of my string.
As soon as you chop that logic path out.
If the lengths are equal you can just use ==
Then it would occur that if you chopped up str
into cs length parts, you could do a straight comparison there as well.
e.g str of TonyJ and search for a three character sequence would pile through
Ton
ony
nyJ
One loop, one if statement and a heck of a lot clearer.

I would suggest using this and using the contains method therein.
Edit - For the reading impaired:
The linked method is not from java.lang.String or java.lang.Object
If you'd bother to actually look at the links, you would see that it is the Apache Commons-Lang API and the StringUtils.contains(...) method that I reference, which very clearly answers the question.

If this is for your homework, which I suspect it is, then I suggest you take a look at the API for the String class to see what other methods are available to help find the location of one String within another.
Also consider looking at the source code for String to see how it implements it.

I'm sure you already know this, but it is in fact possible to see the actual source code of the built-in classes and methods. So I'd take a look there for a start. The String class is especially interesting, IMO.

Related

Count the Characters in a String Recursively & treat "eu" as a Single Character

I am new to Java, and I'm trying to figure out how to count Characters in the given string and threat a combination of two characters "eu" as a single character, and still count all other characters as one character.
And I want to do that using recursion.
Consider the following example.
Input:
"geugeu"
Desired output:
4 // g + eu + g + eu = 4
Current output:
2
I've been trying a lot and still can't seem to figure out how to implement it correctly.
My code:
public static int recursionCount(String str) {
if (str.length() == 1) {
return 0;
}
else {
String ch = str.substring(0, 2);
if (ch.equals("eu") {
return 1 + recursionCount(str.substring(1));
}
else {
return recursionCount(str.substring(1));
}
}
}
OP wants to count all characters in a string but adjacent characters "ae", "oe", "ue", and "eu" should be considered a single character and counted only once.
Below code does that:
public static int recursionCount(String str) {
int n;
n = str.length();
if(n <= 1) {
return n; // return 1 if one character left or 0 if empty string.
}
else {
String ch = str.substring(0, 2);
if(ch.equals("ae") || ch.equals("oe") || ch.equals("ue") || ch.equals("eu")) {
// consider as one character and skip next character
return 1 + recursionCount(str.substring(2));
}
else {
// don't skip next character
return 1 + recursionCount(str.substring(1));
}
}
}
Recursion explained
In order to address a particular task using Recursion, you need a firm understanding of how recursion works.
And the first thing you need to keep in mind is that every recursive solution should (either explicitly or implicitly) contain two parts: Base case and Recursive case.
Let's have a look at them closely:
Base case - a part that represents a simple edge-case (or a set of edge-cases), i.e. a situation in which recursion should terminate. The outcome for these edge-cases is known in advance. For this task, base case is when the given string is empty, and since there's nothing to count the return value should be 0. That is sufficient for the algorithm to work, outcomes for other inputs should be derived from the recursive case.
Recursive case - is the part of the method where recursive calls are made and where the main logic resides. Every recursive call eventually hits the base case and stars building its return value.
In the recursive case, we need to check whether the given string starts from a particular string like "eu". And for that we don't need to generate a substring (keep in mind that object creation is costful). instead we can use method String.startsWith() which checks if the bytes of the provided prefix string match the bytes at the beginning of this string which is chipper (reminder: starting from Java 9 String is backed by an array of bytes, and each character is represented either with one or two bytes depending on the character encoding) and we also don't bother about the length of the string because if the string is shorter than the prefix startsWith() will return false.
Implementation
That said, here's how an implementation might look:
public static int recursionCount(String str) {
if(str.isEmpty()) {
return 0;
}
return str.startsWith("eu") ?
1 + recursionCount(str.substring(2)) : 1 + recursionCount(str.substring(1));
}
Note: that besides from being able to implement a solution, you also need to evaluate it's Time and Space complexity.
In this case because we are creating a new string with every call time complexity is quadratic O(n^2) (reminder: creation of the new string requires allocating the memory to coping bytes of the original string). And worse case space complexity also would be O(n^2).
There's a way of solving this problem recursively in a linear time O(n) without generating a new string at every call. For that we need to introduce the second argument - current index, and each recursive call should advance this index either by 1 or by 2 (I'm not going to implement this solution and living it for OP/reader as an exercise).
In addition
In addition, here's a concise and simple non-recursive solution using String.replace():
public static int count(String str) {
return str.replace("eu", "_").length();
}
If you would need handle multiple combination of character (which were listed in the first version of the question) you can make use of the regular expressions with String.replaceAll():
public static int count(String str) {
return str.replaceAll("ue|au|oe|eu", "_").length();
}

startsWith(String) method and arrays

I have to take a string and convert the string to piglatin. There are three rules to piglatin, one of them being:
if the english word starts with a vowel return the english word + "yay" for the piglatin version.
So i tried doing this honestly expecting to get an error because the startsWith() method takes a string for parameters and not an array.
public String pigLatinize(String p){
if(pigLatRules(p) == 0){
return p + "yay";
}
}
public int pigLatRules(String r){
String vowel[] = {"a","e","i","o","u","A","E","I","O","U"};
if(r.startsWith(vowel)){
return 0;
}
}
but if i can't use an array i'd have to do something like this
if(r.startsWith("a")||r.startsWith("A")....);
return 0;
and test for every single vowel not including y which would take up a very large amount of space, and just personally I would think it would look rather messy.
As i write this i'm thinking of somehow testing it through iteration.
String vowel[] = new String[10];
for(i = 0; i<vowel[]; i++){
if(r.startsWith(vowel[i]){
return 0;
}
I don't know if that attempt at iteration even makes sense though.
Your code:
String vowel[] = new String[10];
for(i = 0; i<vowel[]; i++){
if(r.startsWith(vowel[i]){
return 0;
}
}
Is actually really close to a solution that should work (assuming you actually put some values in the array).
What values do you need to put in it, well as you mentioned you can populate the array with all the possible values for vowels. Those of course being
String[] vowel={"a","A","e","E","i","I","o","O","u","U"};
now you have this you would want to loop (as you worked out) over the array and do your check:
public int pigLatRules(String r){
final String[] vowels={"a","A","e","E","i","I","o","O","u","U"};
for(int i = 0; i< vowels.length; i++){
if(r.startsWith(vowels[i])){
return 0;
}
}
return 1;
}
There are some improvements you can make to this though. Some are best practice some are just choice, some are performance.
As for a best practice, You are currently returning an int from this function. You would be best to change the result of this function to be a boolean value (I recommend looking them up if you have not encountered them).
As for a choice you say you do not like having to have an array with the upercase and lowercase vowels in. Well here is a little bit of information. Strings have lots of methods on them http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html one of them is toLowerCase() which as you can guess lowercases a whole string. if you do this to the work you pass in to your function, you cut the amount of checks you need to do in half.
There is lots more you cam get into but this is just a little bit.
Put all those characters in a HashSet and then just perform a lookup to see if the character is valid or not and return 0 accordingly.
Please go through some example on HashSet insert/lookup. It should be straightforward.
Hope this helps.
Put all the vowels in a string, grab the first char in the word you are testing and just see if your char is in the string of all vowels.

String Trim in Java

I have to trim (including whitespaces within the string) all the strings in a list. I have written a method to do this trim using regex. I am using strArray[i] = trimString(strArray[i]); instead of using an enhanced for loop. I assume since string is immutable this way of assigning back to the same array element is correct. Am I right?
public void trimStringArray(String[] strArray){
if(strArray!= null && strArray.length > 0){
for(int i=0;i<strArray.length;i++){
strArray[i] = trimString(strArray[i]);
}
}
}
Yes, that's fine, and you wouldn't be able to use the enhanced for loop. However, you can simplify your code by getting rid of the length > 0 check - there's no harm in it executing the loop 0 times... and personally I would usually expect the parameter to such a method to be non-null anyway, leading to code like this:
public void trimStringArray(String[] strArray) {
Preconditions.checkNotNull(strArray);
for(int i = 0; i < strArray.length; i++) {
strArray[i] = trimString(strArray[i]);
}
}
(Preconditions.checkNotNull comes from Guava in this case.)
You could leave it accepting null - but do you really have many situations where it's valid to have a null array, but you want to trim everything if it's not?
As a readability thing, I'd also encourage you to include a bit more whitespace - it's definitely a personal preference, but I know I find code with no spaces, such as this, harder to read:
for(int i=0;i<strArray.length;i++){
Yes, your code is correct.
Note that the strArray.length > 0 check is redundant: the loop condition will automatically take care of the case when strArray has zero length.
Yes, it is ok to do. I would add add final in method signature. By adding final you can make sure mistakenly you are not re-assigning references (added safety).
public void trimStringArray(final String[] strArray){

Find a char optimization

So this part of the homework wants us to take a Set of Strings and we will return a List of Strings. In the String Set we will have email addresses ie myname#uark.edu. We are to pull the first part of the email address; the name and put it in the String List.From the above example myname would be put into the List.
The code I currently have uses an iterator to pull a string from the Set. I then use the String.contains("#") as an error check to make sure the String has an # symbol in it. I then start at the end of the string and use the string.charAt("#") to check each char. Once It's found i then make a substring with the correct part and send it to the List.
My problem is i wanted to use something recursive and cut down on operations. I was thinking of something that would divide the string.length()/2 and then use String.contains("#") on the second half first. If that half does contain the # symbol then it would call the functions recursively agin. If the back half did not contain the # symbol then the front half would have it and we would call the function recursively sending it.
So my problem is when I call the function recursively and send it the "substring" once I find the # symbol I will only have the index of the substring and not the index of the original string. Any ideas on how to keep track of it or maybe a command/method I should be looking at. Below is my original code. Any advice welcome.
public static List<String> parseEmail(Set<String> emails)
{
List<String> _names = new LinkedList<String>();
Iterator<String> eMailIt=emails.iterator();
while(eMailIt.hasNext())
{
String address=new String(eMailIt.next());
boolean check=true;
if(address.contains("#"))//if else will catch addresses that do not contain '#' .
{
String _address="";
for(int i=address.length(); i>0 && check; i--)
{
if('#'==address.charAt(i-1))
{
_address=new String(address.substring(0,i-1));
check=false;
}
}
_names.add(_address);
//System.out.println(_address);//fill in with correct sub string
}
else
{
//System.out.println("Invalid address");
_names.add("Invalid address");//This is whats shownn when you have an address that does not have an # in it.
} // could have it insert some other char i.e. *%# s.t. if you use the returned list it can skip over invalid emails
}
return _names;
}
**It was suggested I use the String.indexOf("#") BUT according to the API this method only gives back the first occurrence of the symbol and I have to work on the assumption that there could be multiple "#" in the address and I have to use the last one. Thank you for the suggestion though. Am looking at the other suggestion and will report back.
***So there is a string.lastindexOf() and that was what I needed.
public static List<String> parseEmail(Set<String> emails)
{
List<String> _names = new LinkedList<String>();
Iterator<String> eMailIt=emails.iterator();
while(eMailIt.hasNext())
{
String address=new String(eMailIt.next());
if(address.contains("#"))//if else will catch addresses that do not contain '#' .
{
int endex=address.lastIndexOf('#');
_names.add(address.substring(0,endex-1));
// System.out.println(address.substring(0,endex));
}
else
{
// System.out.println("Invalid address");
_names.add("Invalid address");//This is whats shownn when you have an address that does not have an # in it.
} // could have it insert some other char i.e. *%# s.t. if you use the returned list it can skip over invalid emails
}
return _names;
}
Don't reinvent the wheel (unless you were asked too of course). Java already has a built-in function for what you are attempting String.indexOf(String str). Use it.
final String email = "someone#example.com";
final int atIndex = email.lastIndexOf("#");
if(atIndex != -1) {
final String name = email.substring(0, atIndex);
}
I agree to the previous two answers, if you are allowed to use the built-in functions split or indexOf then you should. However if it is part of your homework to find the substrings yourself you should definitely just go through the string's characters and stop when you found the # aka linear search.
You should definitely not under no circumstances try to do this recursively: The idea of divide and conquer should not be abused in a situation where there is nothing to gain: Recursion means function-call overhead and doing this recursively would only have a chance of being faster than a simple linear search if the sub-strings were searched in-parallel; and even then: the synchronization overhead would kill the speedup for all but the most gigantic strings.
Unless recursion is specified in the homework, you would be best served by looking into String.split. It will split the String into a String array (if you specify it to be around '#'), and you can access both halves of the e-mail address.

Is there an equivalent of ucwords in java

In php, the method ucwords converts any string in a string where each words first character is in uppercase, and all other characters are lower case.
I always end up making my own implementation, and I'm wondering if a standard method exists.
That's called capitalization. Use Apache Commons's StringUtils to do that.
See more here:
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html
WordUtils is also worth looking at. See here
Otherwise it's a rather simple fix such as; String string1 = someString.substring(0,1).toUpperCase() + someString.substring(1);
You can put it in a function, and call it whenever you need. Saves you the trouble of maintaining libraries you don't need. (not that apache commons is ever trouble, but you get the point..)
EDIT: someString.substring(1) part can be written as someString.substring(1).toLowerCase() just to make sure that the rest of the string is in lowercase
I don't know about any direct equivalent, but you can always write one:
public static String capitalize(String input) {
if (input == null || input.length() <= 0) {
return input;
}
char[] chars = new char[1];
input.getChars(0, 1, chars, 0);
if (Character.isUpperCase(chars[0])) {
return input;
} else {
StringBuilder buffer = new StringBuilder(input.length());
buffer.append(Character.toUpperCase(chars[0]));
buffer.append(input.toCharArray(), 1, input.length()-1);
return buffer.toString();
}
}

Categories