Get the location of a substituted format string substring in Android - java

I'm not quite sure how to word this so the title is a bit wierd. What I want to do is to colour and change the size of 2 subsituted substrings in a string that is in the format "%1$d/10 %2$s".
So say for example the first argument is '1' and the second argument is 'Rubbish' the final string would be "1/10 Rubbish". I want to colour the '1' red and set the style to bold, and colour the 'Rubbish' red, but leave the '/10' unchanged. I know I can do this with Spannables but the problem is I cannot see a way to get the start and end points of the various substrings. I know I can just look for the first '/' and assume that the characters before it are the first format substitution, and then look for the first non-space character after the '10' and know that this is the second format substitution but that seems a bit messy. Surely there should be some way to query the string for the positions of the characters that have been substituted for each format parameter?

Not that I know of.
All format methods in Java return either a string or a Formatter(depending on what you're using).
It seems "messy" but not that much, as you said you're probably going to use a variant of indexOf(String str, int fromIndex) twice to get the indexes and then coloring using spannable. So it's probably going to be about 4 to 6 lines of relevant code.
One other way to manually find the indexes is using a for loop to find a '/' and then a ' '. If your string always has this format it will work.
There are regexes as well but it's a bit overkill!

Related

Why is my String array length 3 instead of 2?

I'm trying to understand regex. I wanted to make a String[] using split to show me how many letters are in a given string expression?
import java.util.*;
import java.io.*;
public class Main {
public static String simpleSymbols(String str) {
String result = "";
String[] alpha = str.split("[\\+\\w\\+]");
int alphaLength = alpha.length;
// System.out.print(alphaLength);
String[] charCount = str.split("[a-z]");
int charCountLength = charCount.length;
System.out.println(charCountLength);
}
}
My input string is "+d+=3=+s+". I split the string to count the number of letters in string. The array length should be two but I'm getting three. Also, I'm trying to make a regex to check the pattern +b+, with b being any letter in the alphabet? Is that correct?
So, a few things pop out to me:
First, your regex looks correct. If you're ever worried about how your regex will perform, you can use https://regexr.com/ to check it out. Just put your regex on the top and enter your string in the bottom to see if it is matching correctly
Second, upon close inspection, I see you're using the split function. While it is convenient for quickly splitting strings, you need to be careful as to what you are splitting on. In this case, you're removing all of the strings that you were initially looking at, which would make it impossible to find. If you print it out, you would notice that the following shows (for an input string of +d+=3=+s+):
+
+=3=+
+
Which shows that you accidentally cut out what you were looking to find in the first place. Now, there are several ways of fixing this, depending on what your criteria is.
Now, if what you wanted was just to separate on all +s and it doesn't matter that you find only what is directly bounded by +s, then split works awesome. Just do str.split("+"), and this will return you a list of the following (for +d+=3=+s+):
d
=3=
s
However, you can see that this poses a few problems. First, it doesn't strip out the =3= that we don't want, and second, it does not truly give us values that are surrounded by a +_+ format, where the underscore represents the string/char you're looking for.
Seeing as you're using +w, you intend to find words that are surrounded by +s. However, if you're just looking to find one character, I would suggest using another like [a-z] or [a-zA-Z] to be more specific. However, if you want to find multiple alphabetical characters, your pattern is fine. You can also add a * (0 or more) or a + (1 or more) at the end of the pattern to dictate what exactly you're looking for.
I won't give you the answer outright, but I'll give you a clue as to what to move towards. Try using a pattern and a matcher to find the regex that you listed above and then if you find a match, make sure to store it somewhere :)
Also, for future reference, you should always start a function name with a lower case, at least in Java. Only constants and class names should start in a capital :)
I am trying to use split to count the number of letters in that string. The array length should be two, but I'm getting three.
The regex in the split functions is used as delimiters and will not be shown in results. In your case "str.split([a-z])" means using alphabets as delimiters to separate your input string, which makes three substrings "(+)|d|(+=3=+)|s|(+)".
If you really want to count the number of letters using "split", use 'str.split("[^a-z]")'. But I would recommend using "java.util.regex.Matcher.find()" in order to find out all letters.
Also, I'm trying to make a regex to check the pattern +b+, with b being any letter in the alphabet? Is that correct?
Similarly, check the functions in "java.util.regex.Matcher".

Regex to match a fixed sub string in a String

I am trying to write a regular expression to verify the presence of a specific number in a fixed position in a String.
String: 109300300330066611111111100000000017000656052086116020170111Name 1
Number to find: 111111111 (Staring from position 17)
I have written the following regular expression:
^.{16}(?<Ones>111111111)(.*)
My understanding is:
Let first 16 characters be whatever they are
Use the Named Capturing Group to grab the specific word
Let the rest of the characters be whatever they are
I am new to regex, is there any issue with the above approach?
Can it be done in other/better way?
I am using Java 8.
Without more details of why you're doing what you're doing, there's just one possible improvement I can see. You repeated any character 16 times at the beginning of the string rather than writing out 16 .s, which is nice and readable, but then, it would be nice to do the same for the repeated 1s:
^.{16}(?<Ones>1{9})(.*)
Otherwise, the string of 1s is hard to understand without the coder manually counting how many there are in the regex.
If you want to hard-code the ones and you know the starting position and you just wnat to know if it is there, using a regex seems unnecessary. you can use this:
String s = "109300300330066611111111100000000017000656052086116020170111Name 1";
if (s.indexOf("111111111").equals(16) doSomething();
Another possible solution without regex:
if(s.substring(16,25).equals("111111111") doSomething();
Otherwise your regex looks good.

String.split() returns an array with an additional empty value

I'm working on a piece of code where I've to split a string into individual parts. The basic logic flow of my code is, the numbers below on the LHS, i.e 1, 2 and 3 are ids of an object. Once I split them, I'd use these ids, get the respective value and replace the ids in the below String with its respective values. The string that I have is as follow -
String str = "(1+2+3)>100";
I've used the following code for splitting the string -
String[] arraySplit = str.split("\\>|\\<|\\=");
String[] finalArray = arraySplit[0].split("\\(|\\)|\\+|\\-|\\*");
Now the arrays that I get are as such -
arraySplit = [(1+2+3), >100];
finalArray = [, 1, 2, 3];
So, after the string is split, I'd replace the string with the values, i.e the string would now be, (20+45+50)>100 where 20, 45 and 50 are the respective values. (this string would then be used in SpEL to evaluate the formula)
I'm almost there, just that I'm getting an empty element at the first position. Is there a way to not get the empty element in the second array, i.e finalArray? Doing some research on this, I'm guessing it is splitting the string (1+2+3) and taking an empty element as a part of the string.
If this is the thing, then is there any other method apart from String.split() that would give me the same result?
Edit -
Here, (1+2+3)>100 is just an example. The round braces are part of a formula, and the string could also be as ((1+2+3)*(5-2))>100.
Edit 2 -
After splitting this String and doing some code over it, I'm goind to use this string in SpEL. So if there's a better solution by directly using SpEL then also it would be great.
Also, currently I'm using the syntax of the formula as such - (1+2+3) * 4>100 but if there's a way out by changing the formula syntax a bit then that would also be helpful, e.g replacing the formula by - ({#1}+{#2}+{#3}) *
{#4}>100, in this case I'd get the variable using {# as the variable and get the numbers.
I hope this part is clear.
Edit 3 -
Just in case, SpEL is also there in my project although I don't have much idea on it, so if there's a better solution using SpEL then its more than welcome. The basic logic of the question is written at the starting of the question in bold.
If you take a look at the split(String regex, int limit)(emphasis is mine):
When there is a positive-width match at the beginning of this string then an empty leading substring is included at the beginning of the resulting array.
Thus, you can specify 0 as limit param:
If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded.
If you keep things really simple, you may be able to get away with using a combination of regular expressions and string operations like split and replace.
However, it looks to me like you'd be better off writing a simple parser using ANTLR.
Take a look at Parsing an arithmetic expression and building a tree from it in Java and https://theantlrguy.atlassian.net/wiki/display/ANTLR3/Five+minute+introduction+to+ANTLR+3
Edit: I haven't used ANTLR in a while - it's now up to version 4, and there may be some significant differences, so make sure that you check the documentation for that version.

regular expression Help on - extract a value from a string ignoring the previous contents

can someone help me to write a java regex to retrieve a value from the following string please?
XX0001 15NOV XXX SELECTED RAX AXXXXX DXXXXXXXXX REF NBR 002 SSSS
I wanted to extract the value 002. All the strings / characters before 002 are fixed length and properly padded with trailing space (if req.). could have any string/numeric/special displayable characters.
I am looking for something like ... get 002 from that position ignoring whatever before. ?
What language?
If javascript:
myCode=myString.substring(56,58);
or
myCode=myString.substr(56,3);
If PHP:
$myCode=substr($myString,56,3);
This simpler option is preferable to regex because it is faster. You can use this because you're working with fixed length strings.
EDIT: Just saw your edit referencing Java. So in Java:
String myCode = myString.substring(56,59);
In Java
string.substring(56,59);
You don't need regex to do that. Just use the String method substring:
String myString = originalString.substring(106,109); // myString = "002"
106 is the begin index, and 109 the end index - 1. To simply get the first, just take the length of the original string just before the number you want to get, for instance:
System.out.println("XX0001 15NOV XXX SELECTED RAX AXXXXX DXXXXXXXXX REF NBR ".length());
Assuming that you want the last set of digits before the end of the string, you might want to do something like this:
^.*\\d{3}\\s+.{4}$
This should instruct the Regex Engine to start matching from the beginning of the string, match any characters and then, from the end, match 3 numbers, a space and any 4 characters.
Also, if you have fixed sizes and lengths, you can most likely get away with a .substring method, it is less complex.

Parse a substring?

I'm trying to convert the first two characters of a String using the parseInt method but I cannot. It's supposed to look like this:
String firstChars = IntMessage.substring(0,2);// firstChars is a String that corresponds to the first two characters of the string.
message=ASCII[(Integer.parseInt(firstChar))-32];//The message variable is a String that is supposed to take a firstChars variable and make it an integer so it can be used by the ASCII array in determining which element of the array is to be concatenated to the message String.
For example if the first two characters are 98, I want to take that substring and convert it into an int.
Well, other than the fact that your string is called firstChars and you're trying to parse firstChar, that should work fine.
But this is an area where you should either be using a debugger with breakpoints so you can figure out what values are being placed in the variables, or just print them out:
IntMessage before doing the substring (and shouldn't this normally start with a lower case letter if it's an object?).
firstChars after doing the substring (make sure it's numeric, for example).
Integer.parseInt(firstChars) after that, making sure it's what you expect.
Then Integer.parseInt(firstChars) - 32.
Finally, ASCII[Integer.parseInt(firstChars) - 32].
Then it will be a simple matter of examining all the outputs to see what the problem is.

Categories