Learning java as my first language and I found a solution for the problem at codingbat but I don't understand why my solution doesn't work and would love your help.
Given a string of any length, return a new string where the last 2
chars, if present, are swapped, so "coding" yields "codign".
lastTwo("coding") → "codign" lastTwo("cat") → "cta"
lastTwo("ab") → "ba"
This is my not working code:
public String lastTwo(String str) {
int strLength = str.length();
String last = str.substring(strLength-1,strLength);
String bLast = str.substring(strLength-2,strLength-1);
if(strLength<2)
return str;
return str.substring(0, strLength-2)+last+bLast;
}
This are the errors and I cant figure out why:
lastTwo("a")
→"Exception:java.lang.StringIndexOutOfBoundsException: String
index out of range: -1 (line number:5)" lastTwo("")
→"Exception:java.lang.StringIndexOutOfBoundsException: String
index out of range: -1 (line number:4)"
It seems there is a problem when input is less than 2 chars but I can't figure out why. To me, the if logic looks okay.
You need to move if condition up in the method as:
public static void main(String[] args) {
System.out.println(lastTwo("coding"));
System.out.println(lastTwo("cat"));
System.out.println(lastTwo("ab"));
System.out.println(lastTwo("a"));
}
public static String lastTwo(String str) {
int strLength = str.length();
if(strLength<2)
return str;
String last = str.substring(strLength-1,strLength);
String bLast = str.substring(strLength-2,strLength-1);
return str.substring(0, strLength-2)+last+bLast;
}
This will print:
codign
cta
ba
a
In the method if length of str is less than 2 (e.g. 1) in that case it will be returned else it will compute last and blast and then perform the operation.
When the input is is 1 char, strLength-2 is -1. The methodsubstring throws the error because such index doesn't exist. (The same applies to 0 char and strLength-1)
You have to put this verification on top
if(strLength<2)
return str;
When you have this code, if the string is "", it is trying to get the substring between positions -1,0 and -2,-1. You can't get the substring in a position lower than 0.
int strLength = str.length();
String last = str.substring(strLength-1,strLength);
String bLast = str.substring(strLength-2,strLength-1);
One of the overloads for substring can take the starting index , it figures out the last index. So the following should give you the last two chars:
str.substring(java.lang.Math.max(0,str.length()-2))
public String lastTwo(String str) {
if(str != null ) {
int strLength = str.length();
if (strLength < 2)
return str;
String last = str.substring(strLength-1,strLength);
String bLast = str.substring(strLength-2,strLength-1);
return str.substring(0, strLength-2)+last+bLast;
}
return null;
}
Problem in your code is String bLast = str.substring(strLength-2,strLength-1);
when strLength = 1 and you subtract by 2 and your index will be -1, hence IndexOutOfboundException occure.
Use above code your problem solved.
Simpler solution is to take the start-of-string and
append the last-char and then
append the before-last-char:
public static String lastTwo(String str) {
if (str.length()<2){
return str;
} else{
return str.substring(0, str.length() - 2) +
str.charAt(str.length() - 1) +
str.charAt(str.length() - 2);
}
}
Related
I have a method that extracts a certain substring from a string. This substring consists of the numbers in the string. Then this is parsed to an integer.
Method:
protected int startIndex() throws Exception {
String str = getWorkBook().getDefinedName("XYZ");
String sStr = str.substring(10,13);
return Integer.parseInt(sStr) - 1;
}
Example:
String :
'0 DB'!$B$460
subString :
460
Well, I manually entered the index range for the substring. But I would like to automate it.
My approach:
String str = getWorkBook().getDefinedName("XYZ");
int length = str.length();
String sStr = str.substring(length - 3, length);
This works well for this example.
Now there is the problem that the numbers at the end of the string can also be 4 or 5 digits. If that is the case, I naturally get a NullPointerException.
Is there a way or another approach to find out how many numbers are at the end of the string?
You can use the regex, (?<=\D)\d+$ which means one or more digits (i.e. \d+) from the end of the string, preceded by non-digits (i.e. \D).
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
// Test
System.out.println(getNumber("'0 DB'!$B$460"));
}
static String getNumber(String str) {
Matcher matcher = Pattern.compile("(?<=\\D)\\d+$").matcher(str);
if (matcher.find()) {
return matcher.group();
}
// If no match is found, return the string itself
return str;
}
}
In your case I would recommend to use regex with replaceAll like this:
String sStr = str.replaceAll(".*?([0-9]+)$", "$1");
This will extract the all the digits in the end or your String or any length.
Also I think you are missing the case when there are no digit in your String, for that I would recommend to check your string before you convert it to an Integer.
String sStr = str.replaceAll(".*?([0-9]+)$", "$1");
if (!sStr.isEmpty()) {
return Integer.parseInt(sStr) - 1;
}
return 0; // or any default value
If you just want to get the last number, you can go through the entire string on revert and get the start index:
protected static int startIndex() {
String str = getWorkBook().getDefinedName("XYZ");
if(Character.isDigit(str.charAt(str.length() - 1))) {
for(int i = str.length() - 1; i >= 0; i--){
if(!Character.isDigit(str.charAt(i)))
return i+1;
}
}
return -1;
}
and then print it:
public static void main(String[] args) {
int start = startIndex();
if(start != -1)
System.out.println(getWorkBook().getDefinedName("XYZ").substring(start));
else
System.out.println("No Number found");
}
You will have to add the
Simple and fast solution without RegEx:
public class Main
{
public static int getLastNumber(String str) {
int index = str.length() - 1;
while (index > 0 && Character.isDigit(str.charAt(index)))
index--;
return Integer.parseInt(str.substring(index + 1));
}
public static void main(String[] args) {
final String text = "'0 DB'!$B$460";
System.out.println(getLastNumber(text));
}
}
The output will be:
460
If I were going to do this I just search from the end. This is quite efficient. It returns -1 if no positive number is found. Other return options and the use of an OptionalInt could also be used.
String s = "'0 DB'!$B$460";
int i;
for (i = s.length(); i > 0 && Character.isDigit(s.charAt(i-1)); i--);
int vv = (i < s.length()) ? Integer.valueOf(s.substring(i)) : -1;
System.out.println(vv);
Prints
460
If you know that there will always be a number at the end you can forget the ternary (?:) above and just do the following:
int vv = Integer.valueOf(s.substring(i));
I'm trying to take the last three chracters of any string and save it as another String variable. I'm having some tough time with my thought process.
String word = "onetwotwoone"
int length = word.length();
String new_word = id.getChars(length-3, length, buffer, index);
I don't know how to use the getChars method when it comes to buffer or index. Eclipse is making me have those in there. Any suggestions?
Why not just String substr = word.substring(word.length() - 3)?
Update
Please make sure you check that the String is at least 3 characters long before calling substring():
if (word.length() == 3) {
return word;
} else if (word.length() > 3) {
return word.substring(word.length() - 3);
} else {
// whatever is appropriate in this case
throw new IllegalArgumentException("word has fewer than 3 characters!");
}
I would consider right method from StringUtils class from Apache Commons Lang:
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#right(java.lang.String,%20int)
It is safe. You will not get NullPointerException or StringIndexOutOfBoundsException.
Example usage:
StringUtils.right("abcdef", 3)
You can find more examples under the above link.
Here's some terse code that does the job using regex:
String last3 = str.replaceAll(".*?(.?.?.?)?$", "$1");
This code returns up to 3; if there are less than 3 it just returns the string.
This is how to do it safely without regex in one line:
String last3 = str == null || str.length() < 3 ?
str : str.substring(str.length() - 3);
By "safely", I mean without throwing an exception if the string is nulls or shorter than 3 characters (all the other answers are not "safe").
The above code is identical in effect to this code, if you prefer a more verbose, but potentially easier-to-read form:
String last3;
if (str == null || str.length() < 3) {
last3 = str;
} else {
last3 = str.substring(str.length() - 3);
}
String newString = originalString.substring(originalString.length()-3);
public String getLastThree(String myString) {
if(myString.length() > 3)
return myString.substring(myString.length()-3);
else
return myString;
}
If you want the String composed of the last three characters, you can use substring(int):
String new_word = word.substring(word.length() - 3);
If you actually want them as a character array, you should write
char[] buffer = new char[3];
int length = word.length();
word.getChars(length - 3, length, buffer, 0);
The first two arguments to getChars denote the portion of the string you want to extract. The third argument is the array into which that portion will be put. And the last argument gives the position in the buffer where the operation starts.
If the string has less than three characters, you'll get an exception in either of the above cases, so you might want to check for that.
Here is a method I use to get the last xx of a string:
public static String takeLast(String value, int count) {
if (value == null || value.trim().length() == 0 || count < 1) {
return "";
}
if (value.length() > count) {
return value.substring(value.length() - count);
} else {
return value;
}
}
Then use it like so:
String testStr = "this is a test string";
String last1 = takeLast(testStr, 1); //Output: g
String last4 = takeLast(testStr, 4); //Output: ring
This method would be helpful :
String rightPart(String text,int length)
{
if (text.length()<length) return text;
String raw = "";
for (int i = 1; i <= length; i++) {
raw += text.toCharArray()[text.length()-i];
}
return new StringBuilder(raw).reverse().toString();
}
The getChars string method does not return a value, instead it dumps its result into your buffer (or destination) array. The index parameter describes the start offset in your destination array.
Try this link for a more verbose description of the getChars method.
I agree with the others on this, I think substring would be a better way to handle what you're trying to accomplish.
You can use a substring
String word = "onetwotwoone"
int lenght = word.length(); //Note this should be function.
String numbers = word.substring(word.length() - 3);
Alternative way for "insufficient string length or null" save:
String numbers = defaultValue();
try{
numbers = word.substring(word.length() - 3);
} catch(Exception e) {
System.out.println("Insufficient String length");
}
This method will return the x amount of characters from the end.
public static String lastXChars(String v, int x) {
return v.length() <= x ? v : v.substring(v.length() - x);
}
//usage
System.out.println(lastXChars("stackoverflow", 4)); // flow
I have two strings to compare
String st1 = "database-2.0/version\"25-00\"";
String st2 = "database2.0version25";
I want to determine if st1 contains st2. In the example provided I expect to get Yes as answer because the order of characters in st2 is same is st1 and it only missing some characters. Is any function in Java library to do such comparison? I am aware of st1.indexOf(st2) and st1.contains(st2) but they didn't work in this case, both returned false.
Try this:
String regex = st2.chars()
.mapToObj(i -> String.valueOf((char) i))
.map(str -> ".*+?^${}()|[]\\".contains(str) ? "\\" + str : str)
.collect(Collectors.joining(".*", ".*", ".*"));
boolean contains = st1.matches(regex);
Here's a rundown:
Get a regex string of the shorter string (st2 in our case - hardcoded - you can automate this of-course), adding .* in front and back, and between each character. (.* matches 0 or more of any character).
String.chars() returns an IntStream, convert it to String with type cast
As #Robert suggested, escape special characters with a backslash.
Check of the longer string matches, which effectivelly means it contains all characters of the short string, and maybe more.
What you are looking for is a subsequence, not a substring.
Here's a working solution I found on geeksforgeeks:
// Recursive Java program to check if a string
// is subsequence of another string
import java.io.*;
class SubSequence
{
// Returns true if str1[] is a subsequence of str2[]
// m is length of str1 and n is length of str2
static boolean isSubSequence(String str1, String str2, int m, int n)
{
// Base Cases
if (m == 0)
return true;
if (n == 0)
return false;
// If last characters of two strings are matching
if (str1.charAt(m-1) == str2.charAt(n-1))
return isSubSequence(str1, str2, m-1, n-1);
// If last characters are not matching
return isSubSequence(str1, str2, m, n-1);
}
// Driver program
public static void main (String[] args)
{
String str1 = "database2.0version25";
String str2 = "database2.0/version\"2-00\"";
int m = str1.length();
int n = str2.length();
boolean res = isSubSequence(str1, str2, m, n);
if(res)
System.out.println("Yes");
else
System.out.println("No");
}
}
// Contributed by Pramod Kumar
You can find the subsequence needle in the string haystack by looking for needle's characters in order, starting from an index searchFrom that you update as you find each successive character.
In the following code, note that haystack.indexOf(needleChar, searchFrom) returns the index of the first occurrence of needleChar starting from index searchFrom in haystack.
boolean contains(String haystack, String needle) {
int searchFrom = 0;
for (char needleChar : needle.toCharArray()) {
searchFrom = haystack.indexOf(needleChar, searchFrom);
if (searchFrom == -1) {
return false;
}
}
return true;
}
So I have a string that has several start markers and end markers. How can I make a code that only keeps segments that are between the start and end markers?
A good example would be DNA transcription.
So the starting marker would be TAC, and an end marker would be ACT.
I have a string: AGATACACGACTAGCGAGCTACGATACTACC.
I know how to use the substring method, but not well enough so that it cuts the string down to:
TACACGACTTACGATACT.
How can I do this?
EDIT: I have solved this problem by writing this method:
private String spliceString(String n){
int counter1 = 0;
int startloc = 0;
int endloc = 0;
String m = "";
while (n.indexOf("TAC",counter1) != -1){
startloc = n.indexOf("TAC",counter1);
if (n.indexOf("ACT", counter1) != -1){
endloc = n.indexOf("ACT", counter1);
}
else if (n.indexOf("ATT", counter1) != -1){
endloc = n.indexOf("ATT", counter1);
}
else if (n.indexOf("ATC", counter1) != -1){
endloc = n.indexOf("ATC", counter1);
}
else {
return "AAAA"; //Returns a error string. This will be caught in another method that is not relevant.
}
m = m + n.substring(startloc,endloc + 3);
counter1 = endloc + 1;
}
System.out.println(m); //Just prints out so to check if the code worked
return m;
}
For this, regular expression is your friend.
One way would be to search for what you want to keep, and collect that in a StringBuilder.
String input = "AGATACACGACTAGCGAGCTACGATACTACC";
StringBuilder buf = new StringBuilder();
Matcher m = Pattern.compile("TAC.*?ACT").matcher(input);
while (m.find())
buf.append(m.group());
String output = buf.toString();
System.out.println(output); // prints: TACACGACTTACGATACT
See IDEONE for running code.
Read the javadoc of Pattern for more information on regex.
Alternatively, delete what you don't want to keep, i.e.
Text before first TAC
Text between ACT and TAC
Text after last ACT
The code is much simpler, but the regex is a bit more complex:
String input = "AGATACACGACTAGCGAGCTACGATACTACC";
String output = input.replaceAll("(?<=^|ACT).*?(?=TAC|$)", "");
System.out.println(output); // prints: TACACGACTTACGATACT
See regex101.com for nice color-coded example.
Java - String substring() Method
Description:
This method has two variants and returns a new string that is a substring of this string. The substring begins with the character at the specified index and extends to the end of this string or up to endIndex - 1 If second argument is given.
Syntax:
Here is the syntax of this method:
public String substring(int beginIndex)
or
public String substring(int beginIndex, int endIndex)
Parameters:
Here is the detail of parameters:
beginIndex -- the begin index, inclusive.
endIndex -- the end index, exclusive.
Return Value:
The specified substring.
Example:
import java.io.*;
public class Test{
public static void main(String args[]){
String Str = new String("Welcome to Tutorialspoint.com");
System.out.print("Return Value :" );
System.out.println(Str.substring(10) );
System.out.print("Return Value :" );
System.out.println(Str.substring(10, 15) );
}
}
This produces the following result:
Return Value : Tutorialspoint.com
Return Value : Tuto
I was going through practice questions on CodingBat and I came across this one. It said:
"Given a string and a second "word" string, we'll say that the word matches the string if it appears at the front of the string, except its first char does not need to match exactly. On a match, return the front of the string, or otherwise return the empty string. So, so with the string "hippo" the word "hi" returns "hi" and "xip" returns "hip". The word will be at least length 1. "
So far this is the solution I came up with. It works for the most part, however I get one error shown below:
Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: -1 (line number:3)
This occurs for the case -->> startWord("", "i"). How could this error be fixed?
public String startWord(String str, String word) {
String first = str.substring(1, str.length());
String second = word.substring(1, word.length());
if (str.length() == 0) {
return "";
}
if (str.startsWith(word)) {
return str.substring(0, word.length());
}
else if (first.startsWith(second)) {
return str.substring(0, word.length());
}
return "";
}
You should place your
if (str.length() == 0) {
return "";
}
as a first statement your function, so that the zero length string don't throw the exception.