get matched elements indexes from string object - java

Lets say, search string is
"Hellothisissanjayhelloiamjavadeveloperhello"
And Search pattern is * Hello* I want to get starting and ending indexes of each matched strings like
first Hello--- start index=0, end = 4,
second Hello-- start index=22, end = 26,
like this

Split the text by space.
Iterate and group the word matching hello with corresponding index.
corresponding index will be "Hello Start index".
4 corresponding index + 3 will be "end".

You don't need a regex for this solution. Just simple String#indexOf method in a while loop will give you start and end index.
String input = "Hellothisissanjayhelloiamjavadeveloperhello";
String kw = "hello";
String len = kw.length();
String pos = 0;
int i;
while ((i=input.indexOf(kw, pos)) >= 0) {
pos = i +len;
System.out.println("Starting index=%d, end=%d\n", i, pos);
}

Related

java regex mask all elements in a list with last 4 characters visible

I have a list of alphanumeric strings as below
["nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN"]
I need to mask all elements with last 4 characters visible and [ " must not be masked as below.
["XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4y74","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXdeNv","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX12NN"]
I have tried using
(\\W+)(\\W+)(\\w+)(\\w+)(\\w+)(\\w+)(\\w+)(\\W+)(\\W+)
as the key and $1$2XXXXXXXXXX$4$5$6$7$8$9 as the value in
maskedValue = maskedValue.replaceAll("(\\W+)(\\W+)(\\w+)(\\w+)(\\w+)(\\w+)(\\w+)(\\W+)(\\W+)", "$1$2XXXXXXXXXX$4$5$6$7$8$9")
but this only masked the first element.
["XXXXXXXXXXdeNv","nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74"]
Any leads are appreciated. Thanks in advance.
For a single value, you could use an assertion to match a word character asserting 4 characters at the end of the string.
\w(?=\w*\w{4}$)
Regex demo | Java demo
String values[] = {"nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN"};
for (String element : values)
System.out.println(element.replaceAll("\\w(?=\\w*\\w{4}$)", "X"));
Output
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4y74
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXdeNv
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX12NN
For the whole string, you might use a finite quantifier in a positive lookbehind to match the opening " followed by a number of word characters. Then match all the characters that have 4 character before the closing "
"(?<=\"{0,100})\\w(?=\\w*\\w{4}\")"
Regex demo | Java demo
String regex = "(?<=\"{0,100})\\w(?=\\w*\\w{4}\")";
String string = "[\"nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74\",\"GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv\",\"GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN\"] ";
System.out.println(string.replaceAll(regex, "X"));
Output
["XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4y74","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXdeNv","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX12NN"]
Using a stream:
List<String> terms = Arrays.asList(new String[] {
"nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74",
"GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv",
"GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN"
});
List<String> termsOut = terms.stream()
.map(t -> String.join("", Collections.nCopies(t.length() - 4, "x")) +
t.substring(t.length() - 4))
.collect(Collectors.toList());
System.out.println(termsOut);
This prints:
[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4y74,
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdeNv,
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx12NN]
Note that this solution does not even use regex, which means it may outperform a regex based solution.
Assuming each of these strings will start and end with quotes
Algo:
Use a flag or stack data structure to know if it's a starting quote or ending quote.
For example:
Traverse the string. Initially flag will be false. When you encounter a new quote you have to flip flag and keep traversing till you find other quote. You can do the same with
Stack stack = new Stack<>();
Sample workflow:
String str="random";
boolean flag = false;
int idx = 0;
List<Pair<Integer, Integer>> indices = new ArrayList<>();
StringBuilder string = new StringBuilder(); // for final string
int start;
int end;
while(idx < str.length()){
if (str.charAt(idx) == '"' && !flag){
// start index of string
string.append(s.charAt(idx));
start = idx;
flag = true;
}
else if (str.charAt(idx) == '"' && !flag){
// end index of string
flag = false;
end = idx;
char[] mask = new char[end-3-start];
Arrays.fill(mask, 'x');
string.append(new String(mask)); // need to put 'x' in place
}
if (!flag){
string.append(s.charAt(idx));
}
idx++;
}
Complexity: O(n)

Return the number of times that the string "hi" appears anywhere in the given string

I wrote the following Java code, and it returned a time out error. I'm not exactly sure what that means nor why the code doesn't run
public int countHi(String str) {
int pos = str.indexOf("hi");
int count = 0;
while(pos!=-1)
{
count++;
pos = str.substring(pos).indexOf("hi");
}
return count;
}
I know an alternative solution, using a for loop but I really thought this would work too.
You're getting into an infinite loop because pos never advances past the first match as the first match will be included in the substring.
You can fix by using this overridden version of indexOf() inside your while loop:
pos = str.indexOf("hi", pos + 1);
Or use a do... while loop to avoid having to repeat the call to indexOf():
public static int countHi(String str) {
int pos = -1, count = -1;
do {
count++;
pos = str.indexOf("hi", pos + 1);
} while (pos != -1);
return count;
}
str.substring(pos) Output the substring from the given index. therefore in your code while loop never travel through your whole string and its stop at the first "hi".Use this.
while(pos!=-1){
count++;
str = str.substring(pos+2);
pos = str.indexOf("hi");
}
str variable store 2nd half of the string (use +2 for travel two more indexes for end of the hi) then check pos variable store that index of "hi" appear in the new string.
Just for added fun......
If the supplied substring (ie: "hi") is to be counted and it doesn't matter where it is located within the input string (single word or part of a word), you can use a one liner and let the String.replace() method do the job for you by actually removing the desired substring you want to count from the initial input string and calculating what remains of that input string (this does not modify the initial input string):
String inputString = "Hi there. This is a hit in his pocket";
String subString = "hi";
int count = (inputString.length() - inputString.replace(subString, "").
length()) / subString.length())
//Display the result...
System.out.println(count);
Console will display: 3
You will note that the above code is letter case sensitive and therefore in the example above the substring "hi" differs from the word "Hi" because of the uppercase "H" so "Hi" is ignored. If you want to ignore letter case when counting for the supplied substrings then you can use the same code but utilize the String.toLowerCase() method within it:
String inputString = "Hi there. This is a hit in his pocket";
String subString = "hi";
int count = (inputString.length() - inputString.toLowerCase().
replace(substring.toLowerCase(), "").
length()) / substring.length())
//Display the result...
System.out.println(count);
Console will display: 4
If however the supplied substring you want to count is a specific word (not part of another word) then it gets a little more complicated. One way you can do this is by utilizing the Pattern and Matcher Classes along with a small Regular Expression. It could look something like this:
String inputString = "Hi there. This is a hit in his pocket";
String subString = "Hi";
String regEx = "\\b" + subString + "\\b";
int count = 0; // To hold the word count
// Compile the regular expression
Pattern p = Pattern.compile(regEx);
// See if there are matches of subString within the
// input string utilizing the compiled pattern
Matcher m = p.matcher(inputString);
// Count the matches found
while (m.find()) {
count++;
}
//Display the count result...
System.out.println(count);
Console will display: 1
Again, the above code is letter case sensitive. In other words if the supplied substring was "hi" then the display in console would of been 0 since "hi" is different from "Hi" which is in fact contained within the input string as the first word. If you want to ignore letter case then it would just be a matter of converting both the input string and the supplied substring to either all upper case or all lowercase, for example:
String inputString = "Hi there. This is a hit in his pocket";
String subString = "this is";
String regEx = "\\b" + subString.toLowerCase() + "\\b";
int count = 0; // To hold the word count
// Compile the regular expression
Pattern p = Pattern.compile(regEx);
// See if there are matches of subString within the
// input string utilizing the compiled pattern
Matcher m = p.matcher(inputString.toLowerCase());
// Count the matches found
while (m.find()) {
count++;
}
//Display the count result...
System.out.println(count);
Console will display: 1
As you can see in the two most recent code examples above the Regular Expression (RegEx) of "\\bHi\\b" was used (in code, a variable was used in the place of Hi) and here is what it means:

Remove string after second occurrence of comma in java

String add_filter = address.split("\\,", 2)[0];
This removes the text after the first comma. I need to remove the text after the second comma without using the loop.
address.split("\\,")[2];
That splits the string around commas. THe 0th index is before the first comma, the 1st is after the 1st comma, the 2nd is after the 2nd comma, etc. Note that this code assumes there's at least 2 commas. If there aren't, you need to save the array returned by split() and check the length to make sure its 3 or higher. Otherwise there was no second comma.
try following code :
//Finding the Nth occurrence of a substring in a String
public static int ordinalIndexOf(String str, String substr, int n) {
int pos = str.indexOf(substr);
while (--n > 0 && pos != -1)
pos = str.indexOf(substr, pos + 1);
return pos;
}
then you can remove string after this index position the same as following code :
String newStr = address.substring(0,ordinalIndexOf(address,",",2)- 1)
Try below code
String s = "Hello,world,good bye";
s = s.replaceFirst(",(.*?),.*", " $1");
System.out.println(s);

the first character of first name followed by first character of last name, then the second character of the first name

So i want to arrange the string = "Deepak Pundir" into an order such as "Dpeuenpdaikr" by taking the first character of first name followed by first character of last name, then the second character of the first name, then the second character of the last name, and so on.
Here is a code snippit that shows you a basic algorithm for doing what you want:
String[] components = name.split(" "); // get the first and last names
if(components.length < 2) return; // check for valid string
StringBuilder build = new StringBuilder();
for(int x = 0;x < components[0].length && x < components[1].length;x++)
build.append(components[0].charAt(x) + components[1].charAt(x));
String result = build.toString();
For C, this algorithm is very similiar. You just need to use strtok instead of split:
strtok: get tokens from a string

Delete one part of the String

I have this String :
String myStr = "something.bad#foo.us"
I want to get just the "something.bad" from myStr ?
You just need to use substring having found the right index to chop at:
int index = myStr.indexOf('#');
// TODO: work out what to do if index == -1
String firstPart = myStr.substring(0, index);
EDIT: Fairly obviously, the above takes the substring before the first #. If you want the substring before the last # you would write:
int index = myStr.lastIndexOf('#');
// TODO: work out what to do if index == -1
String firstPart = myStr.substring(0, index);
You can use
String str = myStr.split("#")[0];
It will split the string in two parts and then you can get the first String element

Categories