I have a String for example
String value1 = "12345 abc 123 def 123";
and another one to be searched on it
String value2 ="123";
for example.
How can I return all the indices the 2nd string appears on the first? From what I've searched, indexOf and lastIndexOf searches the string for the first and last index of the specified string.
Use the optional parameter of indexOf.
List<Integer> indexes = new ArrayList<>();
for (int idx = haystack.indexOf(needle);
idx != -1;
idx = haystack.indexOf(needle, idx + 1)) {
indexes.add(idx);
}
Use indexOf(String str, int fromIndex)) in a loop.
Use Regex it is better
class Test {
public static void main(String[] args) {
String value1= "12345 abc 123 def 123";
Pattern pattern = Pattern.compile("123");
Matcher matcher = pattern.matcher(value1);
int count = 0;
while (matcher.find()){
count++;
}
System.out.println(count);
}
}
Try Regexes with Pattern and Matcher.
Then you can get the start indices with matcher.start(), the end indices (exclusive) with matcher.end().
String value1 = "12345 abc 123 def 123";
String value2 = "123";
Pattern pattern = Pattern.compile(value2);
Matcher matcher = pattern.matcher(value1);
while (matcher.find()){
System.out.println("Start: " + matcher.start() + " -- End: " + matcher.end());
}
This will give you as output:
Start: 0 -- End: 3
Start: 10 -- End: 13
Start: 18 -- End: 21
You will need to implement this function yourself. You could use something like:
package com.example.stringutils;
import java.util.ArrayList;
public class Util {
/** Return a list of all the indexes of the 'key' string that occur in the
* 'arbitrary' string. If there are none an empty list is returned.
*
* #param key
* #param arbitrary
* #return
*/
private static ArrayList<Integer> allIndexesOf(String key, String arbitrary) {
ArrayList<Integer> result = new ArrayList<Integer>();
if (key == null | key.length() == 0 | arbitrary == null | arbitrary.length()<key.length()) {
return result;
}
int loc = -1;
while ((loc = arbitrary.indexOf(key, loc+1)) > -1) {
result.add(loc);
}
return result;
}
}
You may want to see if regular expressions actually perform faster (fewer code lines aren't always faster, just simpler "code").
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);
}
I am looking for code that produces the following output in standard output from the following string prepared according to a certain format.
Assumptions and rules:
Each letter is used 2 times in the given string and the letters between the same 2 letters are to be considered child letters.
The given string is always given in proper format. The string format
does not need to be checked.
Example:
Input : abccbdeeda
Expected output:
a
--b
----c
--d
----e
Explanation: since the 2 letters "b" occur between the letters "a", the letter b takes 2 hyphens (--b)
Attempt
public static void main(String[] args) {
String input = "abccbdeeda";
System.out.println("input: " + input);
String[] strSplit = input.split("");
String g = "";
String h = "-";
ArrayList<String> list = new ArrayList<String>();
int counter = 1;
boolean secondNumber;
list.add(strSplit[0]);
int dual = 0;
for (int i = 1; i < strSplit.length; i++) {
secondNumber = list.contains(strSplit[i]);
if ((secondNumber)) {
counter--;
dual = counter * 2;
for (int f = 0; f < dual; f++) {
strSplit[i] = h.concat(strSplit[i]);
}
g = "";
dual = 0;
} else {
list.add(strSplit[i]);
counter++;
}
}
Arrays.sort(strSplit);
for (int p = 0; p < strSplit.length; p++) {
System.out.println(strSplit[p]);
}
}
input: abccbdeeda
My output:
----c
----e
--b
--d
a
I wasn't able to sort the output alphabetically. How can I sort alphabetically with those hyphen characters in them?
This task is nicely done with the help of a stack. If the current character is equal to the top of the stack, then the character is closed and can be removed, otherwise we met it for the first time and it must be added to the stack and the resulting string by adding before it stack.size() * 2 dashes.
When we have completely traversed the string we can sort the resulting string.
public static void main(String[] args) {
Stack<Character> stack = new Stack<>();
String string = "abccbdeeda";
StringBuilder result = new StringBuilder();
for(int i = 0; i < string.length(); i++) {
char curChar = string.charAt(i);
if(!stack.isEmpty() && curChar == stack.peek()) {
stack.pop();
} else {
result.append("-".repeat(stack.size() * 2)).append(curChar).append(" ");
stack.add(curChar);
}
}
System.out.println(result);
System.out.println(Arrays.toString(Arrays.stream(result.toString().split(" ")).sorted().toArray()));
}
Output
a --b ----c --d ----e
[----c, ----e, --b, --d, a]
You can go through the strSplit array and extract the charactors in each element to a separate list/array. To check whether the array element contains a letter you can write a regular expression.
Ex: private final Pattern x = Pattern.compile("[a-z]");
Write a separate method to match the patern to each element in the strSplit array. This method will return the charactor in your input string.
private String findCharactor(final StringBuilder element) {
final Matcher matcher = x.matcher(element);
if (matcher.find()) {
final int matchIndex = matcher.start(); //this gives the index of the char in the string
return element.substring(matchIndex);
}
}
Add these returned charactors to a separate array and sort it using sorting function.
Suppose your result list is:
List<String> resultList = Arrays.asList("----c", "----e", "--b", "--d", "a");
You can sort it alphabetically by a single line:
Collections.sort(resultList, (o1, o2) -> new StringBuilder(o1).reverse().toString().compareTo(new StringBuilder(o2).reverse().toString()));
You can use recursion for a depth-first traversal (preorder):
public static String dfs(String string, String prefix) {
if (string.length() == 0) return "";
int i = string.indexOf(string.charAt(0), 1);
return prefix + string.charAt(0) + "\n" // current
+ dfs(string.substring(1, i), prefix + "--") // all nested
+ dfs(string.substring(i + 1), prefix); // all siblings
}
Example call:
public static void main(String[] args) {
System.out.println(dfs("abccbdeeda", ""));
}
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.
I got a peculiar situation where I need to validate a String.
String has to satisfy some criteria to move further. which are :
String should start with an Integer value whose length should be > 1
and < n
and then followed by alphabets whose length should be from 0 to m (which means alphabet may be present or may not be present)
myString.charAt(0) is giving me if the string starts with Integer.
How to validate it contains only < n integers ?
How to validate it is by > 0 and < n integers followed by 0 to < m alphabets ?
can I get a regular expression to solve it ?
This should work
^\d{1,n - 1}[A-Za-z]{0,m - 1}$
As you want < n. So it should be n-1
DEMO
Code in JAVA
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches
{
static boolean isValid(String x, int n, int m)
{
String pattern = "^\\d{1," + (n - 1) + "}[A-Za-z]{0," + (m - 1) + "}$";
Pattern r = Pattern.compile(pattern);
Matcher t = r.matcher(x);
return t.find();
}
public static void main( String args[] ){
// String to be scanned to find the pattern.
String line = "123abcdef";
int n = 4, m = 4;
if (isValid(line, n, m)) {
System.out.println("FOUND");
} else {
System.out.println("NOT FOUND");
}
}
}
The value of n should be greater than or equal to 2 and the value of m should be greater than 1
IDEONE DEMO
You can match this with a very simple regex:
^(\d+)([A-z]*)$
1 or more digits, followed by 0 or more letters. You can very easily grab the capture groups to find out exactly how many digits or how many letters are in the string. If you know m and n ahead of time as specific numbers, then insert them into the regex like so:
For n = 4 and m = 3,
^(\d{1,4})([A-z]{0,3})$
This will match 0000aaa, but not aaa or 000aaaa.
Another variant of the solution that we have seen so far. All answers are really good. This should also match unicode.
Pattern
\b\p{N}{1,n}\p{L}{0,m}\W
Source Code
public static void matchNumeroAlphaString(){
int n = 3;
int m = 3;
String text =
"John32 54writes about this, 444 and 456Joh writes about that," +
" and John writes #about 9EveryThing. ";
String patternString = "\\b\\p{N}{1," + n + "}\\p{L}{0," + m + "}\\W";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(text);
while(matcher.find()) {
System.out.println("Found: " + matcher.group());
}
}
Output
Found: 444
Found: 456Joh
I have a string something like
(D#01)5(D#02)14100319530033M(D#03)1336009-A-A(D#04)141002A171(D#05)1(D#06)
Now i want to get substring between (D#01)5(D#02)
If i have something like
(D#01)5(D#02)
i can get detail with
quantity = content.substring(content.indexOf("(D#01)") + 6, content.indexOf("(D#02)"));
But somethings D#02 can be different like #05, Now how can i use simple (D# to get string in between. there are multiple repetitions of (D#
Basically this is what i want to do
content.substring(content.indexOf("(D#01)") + 6, content.nextOccurringIndexOf("(D#"));
I suppose you can do
int fromIndex = content.indexOf("(D#01)") + 6;
int toIndex = content.indexOf("(D#", fromIndex); // next occurring
if (fromIndex != -1 && toIndex != -1)
str = content.substring(fromIndex, toIndex);
Output
5
See http://ideone.com/RrUtBy demo.
Assuming that the marker and value are some how linked and you want to know each ((D#01) == 5), then you can make use of the Pattern/Matcher API, for example
String text = "(D#01)5(D#02)14100319530033M(D#03)1336009-A-A(D#04)141002A171(D#05)1(D#06)";
Pattern p = Pattern.compile("\\(D#[0-9]+\\)");
Matcher m = p.matcher(text);
while (m.find()) {
String name = m.group();
if (m.end() < text.length()) {
String content = text.substring(m.end()) + 1;
content = content.substring(0, content.indexOf("("));
System.out.println(name + " = " + content);
}
}
Which outputs
(D#01) = 5
(D#02) = 14100319530033M
(D#03) = 1336009-A-A
(D#04) = 141002A171
(D#05) = 1
Now, this is a little heavy handed, I'd create some kind of "marker" object which contained the key (D#01) and it's start and end indices. I'd then keep this information in a List and cut up each value based on the end of the earlier key and the start of the last key...but that's just me ;)
You can use regex capture groups if want the content between the (D###)'s
Pattern p = Pattern.compile("(\\(D#\\d+\\))(.*?)(?=\\(D#\\d+\\))");
Matcher matcher = p.matcher("(D#01)5(D#02)14100319530033M(D#03)1336009-A-A(D#04)141002A171(D#05)1(D#06)");
while(matcher.find()) {
System.out.println(String.format("%s start: %2s end: %2s matched: %s ",
matcher.group(1), matcher.start(2), matcher.end(2), matcher.group(2)));
}
(D#01) start: 6 end: 7 matched: 5
(D#02) start: 13 end: 28 matched: 14100319530033M
(D#03) start: 34 end: 45 matched: 1336009-A-A
(D#04) start: 51 end: 61 matched: 141002A171
(D#05) start: 67 end: 68 matched: 1
You can user regex to split the input - as suggested by #MadProgrammer. split() method produces a table of Strings, so the order of the occurrences of the searched values will be exactly the same as the order of the values in the table produced by split(). For example:
String input = "(D#01)5(D#02)14100319530033M(D#03)1336009-A-A(D#04)141002A171(D#05)1(D#06)";
String[] table = input.split("\(D#[0-9]+\)");
Try this:
public static void main(String[] args) {
String input = "(D#01)5(D#02)14100319530033M(D#03)1336009-A-A(D#04)141002A171(D#05)1(D#06)";
Pattern p = Pattern.compile("\\(D#\\d+\\)(.*?)(?=\\(D#\\d+\\))");
Matcher matches = p.matcher(input);
while(matches.find()) {
int number = getNum(matches.group(0)); // parses the number
System.out.printf("%d. %s\n", number, matches.group(1)); // print the string
}
}
public static int getNum(String str) {
int start = str.indexOf('#') + 1;
int end = str.indexOf(')', start);
return Integer.parseInt(str.substring(start,end));
}
Result:
1. 5
2. 14100319530033M
3. 1336009-A-A
4. 141002A171
5. 1