I am trying to determine whether a specific digit exists in a String, and do something if so.
See code example:
String pass = "1457";
int i = 4, j=6;
if( /* pass contains i, which is true*/)
// ..do something
if( /* pass contains j, which is false*/)
// ..do something
The problem is I can't find the way to do this.
I have tried -
pass.indexOf(""+i)!=-1
pass.indexOf((char)(i+48))!=-1
pass.contains(""+i)==true
any suggestions?
The problem is I can't find the way to do this. I have tried -any
suggestions?
Code Example : (Execution)
Here we are creating a pattern and then matching it to the string.
import java.util.regex.Pattern;
public class PatternNumber {
public static void main(String args[]) {
String pass = "1457";
int i = 4, j = 6;
Pattern p1 = Pattern.compile(".*[4].*"); // creating a regular expression pattern
Pattern p2 = Pattern.compile(".*[6].*");
if (p1.matcher(pass).matches()) // if match found
System.out.println("contains : " + i);
if (p2.matcher(pass).matches())
System.out.println("contains : " + j);
}
}
Output :
One way to do this is by using Regular Expression :
A regular expression defines a search pattern for strings. The abbreviation for regular expression is regex. The search pattern can be anything from a simple character, a fixed string or a complex expression containing special characters describing the pattern. The pattern defined by the regex may match one or several times or not at all for a given string.
Regular expressions can be used to search, edit and manipulate text.
pass.chars().anyMatch(c -> c == Integer.toString(i).charAt(0))
You can use Integer.toString() to convert integer to string and then find its index in string
Refer code snippet below:-
String pass = "1457";
int i = 4, j = 6;
int index = pass.indexOf(Integer.toString(i));
if (index > -1) // index of i is 1
{
//do something
}
index = pass.indexOf(Integer.toString(j));
if(index < 0) // index of j is -1
{
//do something
}
Related
I have a strange behavior on a really simple problem.
I have a string with a lot of null strings:
"a;b;c;null;null;null;null;null;null;null;null;null;null"
Which I remove using this method:
public String replaceAllNull(String s) {
s = s.replaceAll(";null;", ";;");
//if first item = null remove it
if(s.startsWith("null;")) {
s = s.substring(4,s.length());
}
//if last item = null remove it
if(s.endsWith(";null")) {
s = s.substring(0,s.length()-4);
}
return s;
}
It was working fine until my string became bigger and I saw this strange output
"a;b;c;;null;;null;;null;;null;;"
It's only removing one occurrence out of two.
I think I can understand that during one replace program skips one ";" then the second null is not recognized by my regex ";null;". But I don't get why is this happening?
After one instance of ";null;" is replaced by ";;", then both of the semicolons are already processed, so that the second ; cannot be considered as the start of another replacement for the next ";null;" occurrence. The pattern cannot be matched again until after another "null" has been passed up, to reach the next semicolon.
What you can use is a pattern that doesn't attempt to match the semicolons, but it must check to see if they are there. You can use a positive lookbehind and a positive lookahead (find "lookahead" and "lookbehind" on the linked page). Here, positive means that it verifies that the pattern of the lookbehind/lookahead exists, but doesn't match it.
The positive lookbehind is of the format (?<=X), where X is the pattern to look behind the main pattern to see if it exists. Also, the positive lookahead is of the format (?=X), where X is the pattern to look ahead of the main pattern to see if it exists.
Here, we look for the beginning of the line ^ or a semicolon before the match, and the end of the line $ or a semicolon after the match. Then we simply replace the actual match, "null", with an empty string.
s = s.replaceAll("(?<=^|;)null(?=$|;)", "");
You can use a Stream by splitting the String
return Stream.of(s.split(";", -1))
.map(w -> "null".equals(w) ? "" : w)
.collect(Collectors.joining(";"));
A very simple solution, use this instead of the above big code
public String replaceAllNull(String s) {
return s.replace("null" , "");
}
Example
public static void main(String []args){
String str = "a;r;c;e;null;d;f;e;null;s;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;s;";
System.out.println(String.format("Before replacing null %s", str));
str = replaceAllNull(str);
System.out.println(String.format("After replacing null %s", str));
}
Output
Before replacing null a;r;c;e;null;d;f;e;null;s;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;s;
After replacing null a;r;c;e;;d;f;e;;s;;;;;;;;;;;;;;;;;s;
Update to avoid such words that contains null in it, an alternate is here
public static String replaceAllNull(String s) {
String[] arr = s.split(";");
for (int i = 0; i < arr.length; i++) {
if (arr[i].equalsIgnoreCase("null"))
arr[i] = "";
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
sb.append(arr[i]);
if (i < arr.length - 1)
sb.append(";");
}
if (s.endsWith(";"))
sb.append(";");
return sb.toString();
}
In one of my interview I had asked one program on java string, I am unable to answer it. I don't know it is a simple program or complex one. I have explored on the internet for it, but unable to find the exact solution for it. My question is as follow,
I have supposed one string which contains recursive pattern like,
String str1 = "abcabcabc";
In above string recursive pattern is "abc" which repeated in one string, because this string only contains "abc" pattern recursively.
if I passed this string to a function/method as a parameter that function/method should return me "This string has a recursive pattern." If that string doesn't have any recursive pattern then simply function/method should return "This string doesn't contain the recursive pattern."
Following are probabilities,
String str1 = "abcabcabc";
//This string contains recursive pattern 'abc'
String str2 = "abcabcabcabdac";
//This string doesn't contains recursive pattern
String str2 = "abcddabcddabcddddabc";
//This string contains recursive pattern 'abc' & 'dd'
Can anybody suggest me solution/algorithm for this, I am struggling with it. What is the best way for different probabilities, so that I implement?
From LeetCode
public boolean repeatedSubstringPattern(String str) {
int l = str.length();
for(int i=l/2;i>=1;i--) {
if(l%i==0) {
int m = l/i;
String subS = str.substring(0,i);
StringBuilder sb = new StringBuilder();
for(int j=0;j<m;j++) {
sb.append(subS);
}
if(sb.toString().equals(str)) return true;
}
}
return false;
}
The length of the repeating substring must be a divisor of the length of the input string
Search for all possible divisor of str.length, starting for length/2
If i is a divisor of length, repeat the substring from 0 to i the number of times i is contained in s.length
If the repeated substring is equals to the input str return true
Solution is not in Javascript. However, problem looked interesting, so attempted to solve it in python. Apologies!
In python, I wrote a logic which worked [Could be written much better, thought the logic would help you]
Script is
def check(lst):
return all(x in lst[-1] for x in lst)
s = raw_input("Enter string:: ")
if check(sorted(s.split(s[0])[1:])):
print("String, {} is recursive".format(s))
else:
print("String, {} is NOT recursive".format(s))
Output of the script:
[mac] kgowda#blr-mp6xx:~/Desktop/my_work/play$ python dup.py
Enter string:: abcabcabcabdac
String, abcabcabcabdac is NOT recursive
[mac] kgowda#blr-mp6xx:~/Desktop/my_work/play$ python dup.py
Enter string:: abcabcabc
String, abcabcabc is recursive
[mac] kgowda#blr-mp6xx:~/Desktop/my_work/play$ python dup.py
Enter string:: abcddabcddabcddddabc
String, abcddabcddabcddddabc is recursive
This can also be solved using a part of the Knuth–Morris–Pratt Algorithm.
The idea is to build a 1-D array with each entry representing a character in the word. For each character i in the word we check if there is a prefix which is also a suffix in the word up 0 to i. The reason being if we have common suffix and prefix we can continue searching from the character after prefix ends which we update the array with the corresponding character index.
For s="abcababcababcab", the array will be
Index : 0 1 2 3 4 5 6 7 8
String: a b c a b c a b c
KMP : 0 0 0 1 2 3 4 5 6
For Index = 2, we see that there is no suffix which is also the prefix in the string ab i.e) up until Index = 2
For Index = 4, the suffix ab(Index = 3, 4) is same as the prefix ab(Index = 0, 1) so we update the KMP[4] = 2 which is the index of the pattern from which we have to resume searching.
Thus KMP[i] holds the index of the string s where prefix matches the longest possible suffix in the range 0 to i plus 1. Which essentially means that the a prefix with length index + 1 - KMP[index] exists in the string previously. using this information we can find out if all the substrings of that length are the same.
For Index = 8, we know KMP[index] = 6, which means there is a prefix(s[3] to s[5]) of length 9 - 6 = 3 which is equal to the suffix(s[6] to s[8]), If this is the only repetitive pattern we have this will follow
For a clearer explanation of this algorithm please check this video lecture.
This table can be build in linear time,
vector<int> buildKMPtable(string word)
{
vector<int> kmp(word.size());
int j=0;
for(int i=1; i < word.size(); ++i)
{
j = word[j] == word[i] ? j : kmp[j-1];
if(word[j] == word[i])
{
kmp[i] = j + 1;
++j;
}
else
{
kmp[i] = j;
}
}
return kmp;
}
bool repeatedSubstringPattern(string s) {
auto kmp = buildKMPtable(s);
if(kmp[s.size() -1] == 0) // Occurs when the string has no prefix with suffix ending at the last character of the string
{
return false;
}
int diff = s.size() - kmp[s.size() -1]; //Length of the repetitive pattern
if(s.size() % diff != 0) //Length of repetitive pattern must be a multiple of the size of the string
{
return false;
}
// Check if that repetitive pattern is the only repetitive pattern.
string word = s.substr(0, diff);
int w_size = word.size();
for(int i=0; i < w_size; ++i)
{
int j = i;
while(j < s.size())
{
if(word[i] == s[j])
{
j += w_size;
}
else
{
return false;
}
}
}
return true;
}
If you know the 'parts' in advance, then the answer could be Recursive regular expressions, it seems.
So for abcabcabc we need an expression like abc(?R)* where:
abc matches the literal characters
(?R) recurses the pattern
A * to match between zero and unlimited number of times
The third one is a little trickier. See this regex101 link but it looks like:
((abc)|(dd))(?R)*
where we have either 'abc' or 'dd' and there are any number of these.
Otherwise, I don't see how you could determine from just a string that it has some undefined recursive structure like this.
So I have something like this
System.out.println(some_string.indexOf("\\s+"));
this gives me -1
but when I do with specific value like \t or space
System.out.println(some_string.indexOf("\t"));
I get the correct index.
Is there any way I can get the index of the first occurrence of whitespace without using split, as my string is very long.
PS - if it helps, here is my requirement. I want the first number in the string which is separated from the rest of the string by a tab or space ,and i am trying to avoid split("\\s+")[0]. The string starts with that number and has a space or tab after the number ends
The point is: indexOf() takes a char, or a string; but not a regular expression.
Thus:
String input = "a\tb";
System.out.println(input);
System.out.println(input.indexOf('\t'));
prints 1 because there is a TAB char at index 1.
System.out.println(input.indexOf("\\s+"));
prints -1 because there is no substring \\s+ in your input value.
In other words: if you want to use the powers of regular expressions, you can't use indexOf(). You would be rather looking towards String.match() for example. But of course - that gives a boolean result; not an index.
If you intend to find the index of the first whitespace, you have to iterate the chars manually, like:
for (int index = 0; index < input.length(); index++) {
if (Character.isWhitespace(input.charAt(index))) {
return index;
}
}
return -1;
Something of this sort might help? Though there are better ways to do this.
class Sample{
public static void main(String[] args) {
String s = "1110 001";
int index = -1;
for(int i = 0; i < s.length(); i++ ){
if(Character.isWhitespace(s.charAt(i))){
index = i;
break;
}
}
System.out.println("Required Index : " + index);
}
}
Well, to find with a regular expression, you'll need to use the regular expression classes.
Pattern pat = Pattern.compile("\\s");
Matcher m = pat.matcher(s);
if ( m.find() ) {
System.out.println( "Found \\s at " + m.start());
}
The find method of the Matcher class locates the pattern in the string for which the matcher was created. If it succeeds, the start() method gives you the index of the first character of the match.
Note that you can compile the pattern only once (even create a constant). You just have to create a Matcher for every string.
I am creating a bukkit plugin for minecraft and i need to know a few things before i move on.
I want to check if a text has this layout: "B:10 S:5" for example.
It stands for Buy:amount and Sell:amount
How can i check the easiest way if it follows the syntax?
It can be any number that is 0 or over.
Another problem is to get this data out of the text. how can i check what text is after B: and S: and return it as an integer
I have not tried out this yet because i have no idea where to start.
Thanks for help!
In the simple problem you gave, you can get away with a simple answer. Otherwise, see the regex answer below.
boolean test(String str){
try{
//String str = "B:10 S:5";
String[] arr = str.split(" ");//split to left and right of space = [B:10,S:5]
String[] bArr = arr[0].split(":");//split ...first colon = [B,10]
String[] sArr = arr[1].split(":");//... second colon = [S,5]
//need to use try/catch here in case the string is not an int value.
String labelB = bArr[0];
Integer b = Integer.parseInt(bArr[1]);
String labelS = sArr[0];
Integer s = Integer.parseInt(sArr[1]);
}catch( Exception e){return false;}
return true;
}
See my answer here for a related task. More related details below.
How can I parse a string for a set?
Essentially, you need to use regex and iterate through the groups. Just in case the grammar is not always B and S, I made this more abstract.Also, if there are extra white spaces in the middle for what ever reason, I made that more broad too. The pattern says there are 4 groups (indicated by parentheses): label1, number1, label2, and number2. + means 1 or more. [] means a set of characters. a-z is a range of characters (don't put anything between A-Z and a-z). There are also other ways of showing alpha and numeric patterns, but these are easier to read.
//this is expensive
Pattern p=Pattern.compile("([A-Za-z]+):([0-9]+)[ ]+([A-Za-z]+):([0-9]+)");
boolean test(String txt){
Matcher m=p.matcher(txt);
if(!m.matches())return false;
int groups=m.groupCount();//should only equal 5 (default whole match+4 groups) here, but you can test this
System.out.println("Matched: " + m.group(0));
//Label1 = m.group(1);
//val1 = m.group(2);
//Label2 = m.group(3);
//val2 = m.group(4);
return true;
}
Use Regular Expression.
In your case,^B:(\d)+ S:(\d)+$ is enough.
In java, to use a regular expression:
public class RegExExample {
public static void main(String[] args) {
Pattern p = Pattern.compile("^B:(\d)+ S:(\d)+$");
for (int i = 0; i < args.length; i++)
if (p.matcher(args[i]).matches())
System.out.println( "ARGUMENT #" + i + " IS VALID!")
else
System.out.println( "ARGUMENT #" + i + " IS INVALID!");
}
}
This sample program take inputs from command line, validate it against the pattern and print the result to STDOUT.
I'm facing a problem in replacing character in a string with its index.
e.g I wanna replace every '?' With its index String:
"a?ghmars?bh?" -> will be "a1ghmars8bh11".
Any help is truly appreciated.
P.s I need to solve this assignment today so I can pass it to my instructor.
Thanks in adv.
So far I get to manage replacing the ? With 0; through this piece of code:
public static void main(String[] args) {
String name = "?tsds?dsds?";
String myarray[] = name.split("");
for (int i = 0; i < myarray.length; i++) {
name = name.replace("?", String.valueOf(i++));
}
System.out.println(name);
output:
0tsds0dsds0
it should be:
0tsds5dsds10
For simple replace operations, String.replaceAll is sufficient. For more complex operations, you have to retrace partly, what this method does.
The documentation of String.replaceAll says that it is equivalent to
Pattern.compile(regex).matcher(str).replaceAll(repl)
whereas the linked documentation of replaceAll contains a reference to the method appendReplacement which is provided by Java’s regex package publicly for exactly the purpose of supporting customized replace operations. It’s documentation also gives a code example of the ordinary replaceAll operation:
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString());
Using this template, we can implement the desired operation as follows:
String name = "?tsds?dsds?";
Matcher m=Pattern.compile("?", Pattern.LITERAL).matcher(name);
StringBuffer sb=new StringBuffer();
while(m.find()) {
m.appendReplacement(sb, String.valueOf(m.start()));
}
m.appendTail(sb);
name=sb.toString();
System.out.println(name);
The differences are that we use a LITERAL pattern to inhibit the special meaning of ? in regular expressions (that’s easier to read than using "\\?" as pattern). Further, we specify a String representation of the found match’s location as the replacement (which is what your question was all about). That’s it.
In previous answer wrong read question, sorry. This code replace every "?" with its index
String string = "a?ghmars?bh?das?";
while ( string.contains( "?" ) )
{
Integer index = string.indexOf( "?" );
string = string.replaceFirst( "\\?", index.toString() );
System.out.println( string );
}
So from "a?ghmars?bh?das?" we got "a1ghmars8bh11das16"
You are (more or less) replacing each target with the cardinal number of the occurrence (1 for 1st, 2 for 2nd, etc) but you want the index.
Use a StringBuilder - you only need a few lines:
StringBuilder sb = new StringBuilder(name);
for (int i = name.length - 1; i <= 0; i--)
if (name.charAt(i) == '?')
sb.replace(i, i + 1, i + "");
Note counting down, not up, allowing for the replacement index to be multiple digits, which if you counted up would change the index of subsequent calls (eg everything would get shuffled to the right by one char when the index of "?" was 10 or more).
I think this may work i have not checked it.
public class Stack{
public static void main(String[] args) {
String name = "?tsds?dsds?";
int newvalue=50;
int countspecialcharacter=0;
for(int i=0;i<name.length();i++)
{
char a=name.charAt(i);
switch(a)
{
case'?':
countspecialcharacter++;
if(countspecialcharacter>1)
{
newvalue=newvalue+50;
System.out.print(newvalue);
}
else
{
System.out.print(i);
}
break;
default:
System.out.print(a);
break;
}
}
}
}
Check below code
String string = "a?ghmars?bh?das?";
for (int i = 0; i < string.length(); i++) {
Character r=string.charAt(i);
if(r.toString().equals("?"))
System.out.print(i);
else
System.out.print(r);
}