How to check if some String contains a specific String like "ABC72961". So we search for String which starts with "ABC" following by 5 digits. I've implemented a algorithm but I want it with "matches" or somehow else and then check the speed of these two solutions.
You may want to use regex for this
^ABC[0-9]{5}$
^ : Beginning of the string
ABC : Matches ABC literally (case-sensitive)
[0-9]{5} : Matches 5x numbers from 0 to 9
$ : End of the string
And use String#matches to test it
Regex101
Example
String regex = "^ABC[0-9]{5}$";
String one = "ABC72961";
String two = "ABC2345";
String three = "AB12345";
String four = "ABABABAB";
System.out.println(one.matches(regex)); // true
System.out.println(two.matches(regex)); // false
System.out.println(three.matches(regex)); // false
System.out.println(four.matches(regex)); // false
EDIT
Seeing your comment, you want it to work for String one = "textABC72961text" also. For that to be possible, you should just erase ^ and $ that limit the String.
.*ABC[0-9]{5}.*
EDIT 2
Here is if you want to extract it
if (s.matches(".*ABC[0-9]{5}.*")) {
Matcher m = Pattern.compile("ABC[0-9]{5}").matcher(s);
m.find();
result = m.group();
}
str.contains("ABC72961");
Returns true if str contains the string. False if not.
public String getString() {
String str = extractString();
return str;
}
public boolean exists() {
return !getString().trim().equals("") ? false : true;
}
private List<Integer> getPositionsOfABC() {
List<Integer> positions = new ArrayList<>();
int index = text.indexOf("ABC");
while (index > 0) {
positions.add(index);
index = text.indexOf("ABC", index + 1);
}
return positions;
}
private static boolean isInteger(String str) {
boolean isValidInteger = false;
try {
Integer.parseInteger(str);
isValidInteger = true;
} catch (NumberFormatException ex) {
return isValidInteger;
}
return isValidInteger;
}
private String extractString() {
List<Integer> positions = getPositionsOfABC();
for (Integer position : positions) {
int index = position.intValue();
String substring = text.substring(index, index + LENGTH_OF_DIGITS);
String lastDigits = substring.substring(3, substring.length());
if (isInteger(lastDigits)) {
return substring;
}
}
return "";
}
Here's a simple code that checks whether a substring exists in a string without using library functions, regex or other complex data structures.
class SSC {
public static void main(String[] args) {
String main_str <-- MAIN STRING
String sub_str <-- SUBSTRING
String w; int flag=0;
for(int i=0;i<=main_str.length()-sub_str.length();i++){
w="";
for(int j=0;j<sub_str.length();j++){
w+=main_str.charAt(i+j);
}
if(w.equals(sub_str))
flag++;
}
if(flag>0)
System.out.print("exists "+flag+" times");
else
System.out.print("doesn't exist");
}
}
Hope this helps.
I think what you want to use is java.util.regex.Pattern.
Pattern p = Pattern.compile("ABC(\d*)");
Matcher m = p.matcher("ABC72961");
boolean b = m.matches();
or if it shall be exactly 5 digits after "ABC", you can use the regex ABC(\d{5})
https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#compile(java.lang.String)
Another solution would be:
String stringToTest = "ABC72961"
boolean b = stringToTest.contains("ABC");
http://www.tutorialspoint.com/java/lang/string_contains.htm
You can use the String indexOf command like this:
int result = someString.indexOf("ABC72961")
result will be -1 if there are no matches.
If there is a match, the result will be the index where the match starts.
Related
write a function which increments a string, to create a new string.
If the string already ends with a number, the number should be incremented by 1.
If the string does not end with a number. the number 1 should be appended to the new string.
Examples:
foo - foo1
foobar23 - foobar24
foo0042 - foo0043
foo9 - foo10
foo099 - foo100
Attention: If the number has leading zeros the amount of digits should be considered.
The program passed tests on the CodeWars platform, except for one
For input string: "1712031362069931272877416673"
she falls on it
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
but in IJ it works correctly ...
Any idea why?
import java.math.BigInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
System.out.println(incrementString("foo001"));
System.out.println(incrementString("33275375531813209960"));
System.out.println(incrementString("0000004617702678077138438340108"));
}
public static String incrementString(String str) {
boolean isNumeric = str.chars().allMatch( Character::isDigit );
if(str.isEmpty())
return "1";
else if (isNumeric) {
BigInteger b = new BigInteger(str);
return String.format("%0"+str.length() + "d",b.add(BigInteger.valueOf(1)));
}
String timeRegex = "(.*)(\\D)([0-9]*)";
Pattern pattern = Pattern.compile(timeRegex);
Matcher matcher = pattern.matcher(str);
if (matcher.matches()) {
String sec = matcher.group(3);
StringBuilder sb = new StringBuilder();
if (sec.isEmpty()) {
sec = "0";
return str + sb+(Integer.parseInt(sec) + 1);
} else {
int length = String.valueOf(Integer.parseInt(sec) + 1).length();
if (sec.length() > length) {
for (int i = length; i < sec.length(); i++) {
sb.append("0");
}
}
return str.substring(0,str.length() - sec.length()) + String.format("%0"+sec.length() + "d",Integer.parseInt(sec)+1);
}
}
else
return "";
}
}
The issue is with Integer.parseInt(sec) when trying to parse a value too long to fix in a int (max is 2 billion)
You need to use BigInteger everywhere, also there is much useless code. You can also capture the zeros in the first group of the regex, so you don't have leading zeros to take care
public static String incrementString(String str) {
boolean isNumeric = str.chars().allMatch(Character::isDigit);
if (str.isEmpty()) {
return "1";
} else if (isNumeric) {
BigInteger b = new BigInteger(str);
return String.format("%0" + str.length() + "d", b.add(BigInteger.ONE));
}
String timeRegex = "(.*\\D0*)([1-9][0-9]*)";
Matcher matcher = Pattern.compile(timeRegex).matcher(str);
if (matcher.matches()) {
String sec = matcher.group(2);
if (sec.isEmpty()) {
return str + 1;
} else {
BigInteger new_value = new BigInteger(sec).add(BigInteger.ONE);
return matcher.group(1) + new_value;
}
}
return "";
}
How would you solve this problem by hand? I'll bet you wouldn't require a calculator.
The way I would do would be to just look at the last character in the string:
If the string is empty or the last character is not a digit, append the character 1.
If the last character is one of the digits 0 to 8, change it to the next digit.
If the last character is the digit 9:
Remove all the trailing 9s
Apply whichever of (1) or (2) above is appropriate.
Append the same number of 0s as the number of 9s you removed.
You can implement that simple algorithm in a few lines, without BigInteger and without regexes.
This seems to work, although I didn't test it thoroughly with different Unicode scripts (and I'm really not a Java programmer):
public static String incrementString(String str) {
if (str.isEmpty())
return "1";
char lastChar = str.charAt(str.length()-1);
if (!Character.isDigit(lastChar))
return str + "1";
String prefix = str.substring(0, str.length()-1);
if (Character.digit(lastChar, 10) != 9)
return prefix + (char)(lastChar + 1);
return incrementString(prefix) + (char)(lastChar - 9);
}
INPUT : 123ABC458
OUTPUT : 321ABC854
public static void main(String []args){
String str="123ABC564";
int count=0;
int ans=0;
int firstindex=0;
char[] ch = str.toCharArray();
for(int i=0;i<ch.length;i++){
if(Character.isDigit(ch[i])){
if(ans==0){
firstindex=i;
}
count++;
}
else{
int lastindex=count+firstindex-1;
while(firstindex<lastindex){
char temp=ch[firstindex];
ch[firstindex]=ch[lastindex];
ch[lastindex]=temp;
firstindex++;
lastindex--;
}
ans=0;
count=0;
firstindex=0;
}
}
for (char c : ch){
System.out.print(c);
}
}
}
Can anyone tell me what's wrong with this code
The output which I am getting using this code is 12BA3C564
You can use the Java regex API and StringBuilder to solve it easily. The regex, \d+ specifies one or more digits. Using the Java regex API, you find the numbers, their start position and the end positions which you can use to build the required string.
Demo:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
// Tests
String[] samples = { "123ABC458", "123ABC458XYZ", "123ABC458XYZ367", "ABC123XYZ", "ABC123XYZ" };
for (String s : samples)
System.out.println(numbersInverted(s));
}
static String numbersInverted(String str) {
StringBuilder sb = new StringBuilder();
Matcher matcher = Pattern.compile("\\d+").matcher(str);
int lastInitialPos = 0;
while (matcher.find()) {
int start = matcher.start();
String inverted = new StringBuilder(matcher.group()).reverse().toString();
sb.append(str.substring(lastInitialPos, start)).append(inverted);
lastInitialPos = matcher.end();
}
if (sb.length() == 0) // If no number was found
return str;
else
return sb.append(str.substring(lastInitialPos)).toString();
}
}
Output:
321ABC854
321ABC854XYZ
321ABC854XYZ763
ABC321XYZ
ABC321XYZ
ONLINE DEMO
Here is a concise version using string splitting:
String input = "123ABC458";
String[] parts = input.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
StringBuilder sb = new StringBuilder();
for (String part : parts) {
if (part.matches("\\d+")) {
StringBuilder num = new StringBuilder(part);
sb.append(num.reverse());
}
else {
sb.append(part);
}
}
System.out.println(sb.toString()); // 321ABC854
The splitting operation used above generates a string array of either numbers or letters. Then, we iterate that array and selectively reverse the number strings using StringBuilder#reverse.
This task can be implemented without regular expressions, splitting the input string into substring etc. merely with the help of StringBuilder::insert(int offset, char c) and StringBuilder::append(char c) using simple index calculation for insert:
public static String revertDigits(String str) {
if (str == null || str.isEmpty()) {
return str;
}
StringBuilder sb = new StringBuilder(str.length());
for (int i = 0, j = 0, n = str.length(); i < n; i++) {
char c = str.charAt(i);
if (Character.isDigit(c)) {
sb.insert(j, c); // append in "reverse" mode
} else {
sb.append(c);
j = i + 1; // store the last position of a non-digit
}
}
return sb.toString();
}
Test:
String str="123ABC564";
System.out.println(str + '\n' + revertDigits(str));
Output
123ABC564
321ABC465
Can anyone tell me what's wrong with this code
I believe I have spotted two bugs in your code:
You are never setting ans to anything else than 0. So your if condition ans==0 will always be true. If I have understood the purpose of that variable correctly, you may want to replace it with a boolean called something like insideNumber and set it to true when you detect a digit and to false when you detect that a char is not a digit. Your if statement then becomes if (insideNumber) …
You don’t take a number at the end of your string into account. You can check this statement by appending a letter to your string and see that 564 will then be reversed into 465. To reverse a trailing number correctly: after your loop again check whether you were inside a number, and if so, reverse the last number from firstindex up to the end of the string.
You can get all the numbers from the string as the first move, and then replace the input with the reversed string of the numbers. Example:
public static void main(String[] args)
{
String input = "123ABC458";
Matcher m = Pattern.compile("\\d+").matcher(input);
while(m.find())
input = input.replace(m.group(), new StringBuilder(m.group()).reverse());
System.out.println(input);
}
As an alternative solution, from Java 9 you could also make use of Matcher#replaceAll and reverse every match for 1 or more digits.
String result = Pattern.compile("\\d+")
.matcher("123ABC458")
.replaceAll(m -> new StringBuilder(m.group()).reverse().toString());
System.out.println(result);
Output
321ABC854
Java demo
Given two small String of different length and one full String. Check if the full String is merged from two small String.
Example1: Input - "beautiful", "bauful", "eti" Output - true
Example2: Input - "beautiful", "baufl", "eti" Output - false
That means the characters in small String 1 and small String 2 are in the same order as in full String.
Here is my code:
public class StringMerger {
public static boolean isMerge(String s, String part1, String part2) {
StringBuilder sb = new StringBuilder();
int minLength = Math.min(part1.length(), part2.length());
int maxLength = Math.max(part1.length(), part2.length());
for(int i = 0; i < minLength; i++){
sb.append(part1.charAt(i)).append(part2.charAt(i));
}
for(int i = minLength; i < maxLength; i++){
if(part1.length() >= part2.length()) sb.append(part1.charAt(i));
else sb.append(part2.charAt(i));
}
String temp = sb.toString();
return (temp.equalsIgnoreCase(s)) ? true : false;
}
}
But I have only solve with: Input - "beautiful", "batfl", "euiu" Output - true. This is only one of that' cases. So how to solve it?
Checkout the below solution, you are welcome to break it
Edit1 Fix bug: the bug is not due to the space, it is because when there is a character match in both small strings, the algorithm need to examine which character to take by checking both alternatives
Edit2 Reduce unnecessary depth first search to improve efficiency
public class StringMerger {
public static void main(String[] args) {
System.out.println(isMerge("beautiful", "bauful", "eti")); // true
System.out.println(isMerge("beautiful", "baufl", "eti")); // false
System.out.println(isMerge("bbbbb", "bbb", "bb")); // true
System.out.println(isMerge("xyzxyz", "xyz", "xyz")); // true
System.out.println(isMerge("xyzxyz", "xyz", "xyzd")); // false
System.out.println(isMerge("backstreetboy", "beetb", "ackstroy")); // true
System.out.println(isMerge("Can we merge it? Yes, we can!", "Cn w riYes n!", "aemege t? , weca")); //true
System.out.println(isMerge("beautifulxyzx", "baufulx", "etixyz")); // true
}
public static boolean isMerge(String s, String part1, String part2) {
if (s.length() != part1.length() + part2.length()) return false;
int part1Counter = 0;
int part2Counter = 0;
int fullStrLen = s.length();
int fullStrCounter = 0;
while (fullStrCounter < fullStrLen) {
boolean part1match = part1Counter < part1.length() && s.charAt(fullStrCounter) == part1.charAt(part1Counter);
boolean part2match = part2Counter < part2.length() && s.charAt(fullStrCounter) == part2.charAt(part2Counter);
if (part1match && part2match) { // if find a match in both substring, we need to find out whichever way works
boolean decision1 = isMerge(s.substring(fullStrCounter + 1), part1.substring(part1Counter + 1), part2.substring(part2Counter));
if (decision1) return decision1; // no need to check the second branch if the first branch matches
boolean decision2 = isMerge(s.substring(fullStrCounter + 1), part1.substring(part1Counter), part2.substring(part2Counter + 1));
return decision2;
}
if (part1match) {
++part1Counter;
++fullStrCounter;
} else if (part2match) {
++part2Counter;
++fullStrCounter;
} else {
return false;
}
}
return true;
}
}
Here's a shorter method. It makes use of Arrays.
private static boolean isMerge(String original, String one, String two){
String combinedStrings = one + two;
char[] mergedStrings = combinedStrings.toCharArray();
char[] originalString = original.toCharArray();
Arrays.sort(mergedStrings);
Arrays.sort(originalString);
return Arrays.equals(mergedStrings, originalString);
}
A possible brute-force starting algorithm, without giving you the solution for your homework:
Walk the word String looking for matches in each candidate String.
If there is no match (or both Strings are exhausted), then return False.
If there is a match, move the index for this candidate String.
If we exhaust the word String and all candidate Strings, return True.
I'm hand-waving past the edge conditions here, which would ideally be caught by tests.
It occurs to me that this class should be able to generate candidate Strings from any word String, meaning that you could even make the class symmetric.
i have a list of files in this form:
name_of_file_001.csv
name_of_file_002.csv
name_of_file_123.csv
or
name_of_file.csv
second_name_of_file.csv
i don't know if the file has 001 or not.
how to take name of file (only name_of_file) in java?
Try the following:
int i=0;
while(!fullName.charAt(i).equals('.')&&!fullName.charAt(i).equals('0')){
i++;
}
String name=fullName.substring(0, i);
Take the string from the beginning of the fullName to the first appearance of . or 0.
EDIT:
Referring to the comments and the case of high numbers greater than 1.. and inspired from this answer:
int i=0;
String patternStr = "[0-9\.]";
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(fullName);
if(matcher.find()){
i=matcher.start(); //this will give you the first index of the regex
}
String name=fullName.substring(0, i);
EDIT2:
In the case where there's no Extension and the fullname doesn't match the regex(there's no numbers):
if(matcher.find()){
i=matcher.start(); //this will give you the first index of the regex
}else {
i=fullname.length();
}
String name=fullName.substring(0, i);
Or simply we will take all the name.
I modified chsdk's solution with respect to mmxx's comment:
int i=0;
while(i < fullName.length() && ".0123456789".indexOf(fullName.charAt(i)) == -1) {
i++;
}
String name=fullName.substring(0, i);
EDIT:
Added
i < fullName.length()
This little class solves the problem for all the examples shown in main:
public class Example {
private static boolean isNaturalNumber(String str)
{
return str.matches("\\d+(\\.\\d+)?");
}
public static String getFileName(String s) {
String fn = s.split("\\.")[0];
int idx = fn.lastIndexOf('_');
if (idx < 0) {
return fn;
}
String lastPart = fn.substring(idx+1);
System.out.println("last part = " + lastPart);
if (isNaturalNumber(lastPart)) {
return fn.substring(0,idx);
} else {
return fn;
}
}
public static void main(String []args){
System.out.println(getFileName("file_name_001.csv"));
System.out.println(getFileName("file_name_1234.csv"));
System.out.println(getFileName("file_name.csv"));
System.out.println(getFileName("file_name"));
System.out.println(getFileName("file"));
}
}
EDIT 1: Replaced the exception-based check with a regex check.
EDIT 2: Handling file names without any underscores.
i resolved the problem in this mode:
nameOfFile.split("\\.")[0].replaceall("_[0-9]*","");
split("\.")[0] remove ".csv" name_of_file_001.csv => name_of_file_001
.replaceall("_[0-9]*","") "remove, if there is, "_001" name_of_file_001 => name_of_file
the result is the name of file only
I got a string like this:
string = "item=somevalue&user=user1";
And I need to find a way to extract, in Java, the substring "somevalue" (i.e. the substring after item= and before &).
JUst use a positive lookbehind and positive lookahead assertions like below,
(?<=item=).*?(?=&)
OR
(?<=item=)[^&]*(?=&)
Explanation:
(?<=item=) string which preceeds the match must be ietm=
[^&]* Match any character but not of & symbol zero or more times.
(?=&) Character which follows the match must be & symbol.
Code:
String s = "item=somevalue&user=user1";
Pattern regex = Pattern.compile("(?<=item=).*?(?=&)");
Matcher matcher = regex.matcher(s);
while(matcher.find()){
System.out.println(matcher.group(0));
}
Output:
somevalue
Try following code:
String test= "item=somevalue&user=user1";
String tok[]=test.split("&");
String finalTok[]=tok[0].split("=");
System.out.println(finalTok[1]);
Output :
somevalue
public static void main(String[] args) {
String str = "item=somevalue&user=user1";
String result = "item=somevalue&user=user1".substring(str.indexOf("=") + 1, str.indexOf("&"));
System.out.println(result);
}
Output:
somevalue
One line solution!
System.out.println(string.substring(string.indexOf("=")+1, string.indexOf("&")));
Or
if in case 'somevalue' place is changed add following code!
string = "user=user1&item=somevalue"; System.out.println(string.substring(string.lastIndexOf("=")+1));
Splitting strings on special characters is an often required task and in my opinion regex is quite overkill and has bad performance for such a simple task. Everybody should have some performant string utils for often used task.
e.g. you can do this
for (String s : splitToIterable(str, '&')) {
if (s.startsWith("item=")) {
String itemValue = s.substring(5);
}
}
if you have a helper method like this
public static Iterable<String> splitToIterable(final String str, final char delim) {
if (str == null) {
return null;
}
return new Iterable<String>() {
public Iterator<String> iterator() {
return new Iterator<String>() {
int lastIndex = 0;
String next = fetchNext();
public boolean hasNext() {
return next != null;
}
public String next() {
if (next == null) {
throw new NoSuchElementException();
}
String result = next;
next = fetchNext();
return result;
}
public String fetchNext() {
if (lastIndex == -1) {
return null;
}
String next;
int i = str.indexOf(delim, lastIndex);
if (i > -1) {
next = str.substring(lastIndex, i);
lastIndex = i + 1;
}
else {
next = str.substring(lastIndex);
lastIndex = -1;
}
return next;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}