Erasing String that contains null - java

I have a null value in my message or println that i want to delete, all succeed when i just using code like this.
the message before :
message = 2014-06-02 14:53:37.103 null tes
Here is the code that delete the null word.
public static void main(String[] args) {
//final int month = Integer.parseInt(period[0]), year = Integer.parseInt(period[1]);
Date x = new Date();
Timestamp t = new Timestamp(x.getTime());
String a = "null";
String b = t+" " +a + " tes";
String tes = (b.trim()!= null && b.trim().length()>=23) ? b.trim().replaceFirst(b.trim().substring(0,28), ""+t) : b;
System.out.println("message = " + tes);
}
The printout is right. its like this :
message = 2014-06-02 14:53:37.103 tes
But when i insert this | the printout gone wrong. i'm using that as a separator.
This is the code that went wrong.
public static void main(String[] args) {
//final int month = Integer.parseInt(period[0]), year = Integer.parseInt(period[1]);
Date x = new Date();
Timestamp t = new Timestamp(x.getTime());
String a = "null";
String b = t+"| " +a + " tes";
String tes = (b.trim()!= null && b.trim().length()>=23) ? b.trim().replaceFirst(b.trim().substring(0,28), ""+t) : b;
System.out.println("message = " + tes);
}
And this is the print out :
message = 2014-06-02 14:58:03.148| null tes
What happen to the second code actually?
Thanks

As Boris said there are other ways, but the main problem is that replaceFirst takes a regex and pipe is a special character in regex.
Below with the introduction of Pattern.quote the code should work:
b.trim().replaceFirst(Pattern.quote(b.trim().substring(0,28)), ""+t)

If you want to simply strip out the 'null' text string without the regEx issues above, and quickly and cleanly, just replace the 'null' String directly.
b.replace("null", "")

What is exactly the main purpose of the program? if it is just to remove the null in the String, I would do as JamasA says. Otherwise if you want to get the timestamp and the "tes" string in two clean strings I would do it in this way:
String tes = b.replace("null", "");
String[] aux = tes.split("\\|");
for (int i = 0; i < aux.length; i++) {
System.out.println(aux[i].trim());
}
In this way you get both information separated.I hope it will helpful for you :)

Related

Java - parse user defined functions

I am working on a program, where I want users to define a simple functions like
randomInt(0,10)
or
randomString(10)
instead of static arguments. What is the best way to parse and process such functions ?
I have not found any examples of such problem, the parser does not have to be ultra-efficient, it will not be called often, but mainly I want to focus on good code readability and scalability.
Example of user input:
"This is user randomString(5) and he is randomInt(18,60) years old!"
Expected output(s):
"This is user phiob and he is 45 years old!"
"This is user sdfrt and he is 30 years old!"
One option is to use Spring SPEL. But it forces you to change the expression a little and use Spring library:
The expression can look like this:
'This is user ' + randomString(5) + ' and he is ' + randomInt(18,60) + ' years old!'
or this:
This is user #{randomString(5)} and he is #{randomInt(18,60)} years old!
or you can implement your own by having a custom TemplateParserContext.
And here is the code:
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class SomeTest {
#Test
public void test() {
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(
"This is user #{randomString(5)} and he is #{randomInt(18,60)} years old!",
new TemplateParserContext() );
//alternative
//Expression exp = parser.parseExpression(
// "'This is user ' + randomString(5) + ' and he is ' + randomInt(18,60) + ' years old!'");
// String message = (String) exp.getValue( new StandardEvaluationContext(this) );
String message = (String) exp.getValue( new StandardEvaluationContext(this) );
}
public String randomString(int i) {
return "rs-" + i;
}
public String randomInt(int i, int j) {
return "ri-" + i + ":" + "j";
}
}
Whatever object you pass to StandardEvaluationContext should have those methods. I put them in the same class that also runs the expression.
You could use something such as the following:
Warning, I haven't tested it. Just something to get started with
public String parseInput(String input){
String[] inputArray = input.split(" ");
String output = "";
for(String in : inputArray){ //run through each word of the user input
if(in.contains("randomString(")){ //if the user is calling randomString
String params = in.replace("randomString(", ""); //strip away function to get to params
params = in.replace("(", ""); //strip away function to get to params
String[] paramsArray = params.split(","); //these are string integers, and could be converted
//send off these split apart parameters to your randomString method
String out = randomString(paramsArray); //method parses string integers, outputs string
output += out + " ";
}else if(in.contains("randomInt(")){ //if the user is calling randomInt
String params = in.replace("randomInt(", ""); //strip away function to get to params
params = in.replace("(", ""); //strip away function to get to params
String[] paramsArray = params.split(","); //these are string integers, and could be converted
//send off these split apart parameters to your randomInt method
String out = randomInt(paramsArray); //method parses string integers, outputs string
output += out + " ";
}else{ //if the user is just entering text
output += in + " "; //concat the output with what the user wrote plus a space
}
}
return output;
}

Multiple string replacements without affecting substituted text in subsequent iterations

I've posted about letters earlier, but this is an another topic, I have a json response that contain 2 objects, from and to , from is what to change, and to is what it will be changed to .
My code is :
// for example, the EnteredText is "ab b test a b" .
EnteredString = EnteredText.getText().toString();
for (int i = 0; i < m_jArry.length(); i++) {
JSONObject jo_inside = m_jArry.getJSONObject(i);
String Original = jo_inside.getString("from");
String To = jo_inside.getString("to");
if(isMethodConvertingIn){
EnteredString = EnteredString.replace(" ","_");
EnteredString = EnteredString.replace(Original,To + " ");
} else {
EnteredString = EnteredString.replace("_"," ");
EnteredString = EnteredString.replace(To + " ", Original);
}
}
LoadingProgress.setVisibility(View.GONE);
SetResultText(EnteredString);
ShowResultCardView();
For example, the json response is :
{
"Response":[
{"from":"a","to":"bhduh"},{"from":"b","to":"eieja"},{"from":"tes","to":"neesj"}
]
}
String.replace() method won't work here, because first it will replace a to bhduh, then b to eieja, BUT here's the problem, it will convert b in bhduh to eieja, which i don't want to.
I want to perfectly convert the letters and "words" in the String according the Json, but that what i'm failing at .
New Code :
if(m_jArry.length() > 0){
HashMap<String, String> m_li;
EnteredString = EnteredText.getText().toString();
Log.i("TestAf_","Before Converting: " + EnteredString);
HashMap<String,String> replacements = new HashMap<String,String>();
for (int i = 0; i < m_jArry.length(); i++) {
JSONObject jo_inside = m_jArry.getJSONObject(i);
String Original = jo_inside.getString("from");
String To = jo_inside.getString("to");
if(isMethodConvertingIn){
//EnteredString = EnteredString.replace(" ","_");
replacements.put(Original,To);
Log.i("TestAf_","From: " + Original + " - To: " + To + " - Loop: " + i);
//EnteredString = EnteredString.replace(" ","_");
//EnteredString = EnteredString.replace(Original,To + " ");
} else {
EnteredString = EnteredString.replace("_"," ");
EnteredString = EnteredString.replace("'" + To + "'", Original);
}
}
Log.i("TestAf_","After Converting: " + replaceTokens(EnteredString,replacements));
// Replace Logic Here
// When Finish, Do :
LoadingProgress.setVisibility(View.GONE);
SetResultText(replaceTokens(EnteredString,replacements));
ShowResultCardView();
Output :
10-10 19:51:19.757 12113-12113/? I/TestAf_: Before Converting: ab a ba
10-10 19:51:19.757 12113-12113/? I/TestAf_: From: a - To: bhduh - Loop: 0
10-10 19:51:19.757 12113-12113/? I/TestAf_: From: b - To: eieja - Loop: 1
10-10 19:51:19.757 12113-12113/? I/TestAf_: From: o - To: neesj - Loop: 2
10-10 19:51:19.758 12113-12113/? I/TestAf_: After Converting: ab a ba
You question would be clearer if you gave the expected output for the function.
Assuming it is: ab b test a b >>>> bhduheieja eieja neesjt bhduh eieja
then see the following, the key point in the Javadoc being "This will not repeat"
http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/StringUtils.html#replaceEach(java.lang.String,%20java.lang.String[],%20java.lang.String[])
Replaces all occurrences of Strings within another String.
A null reference passed to this method is a no-op, or if any "search
string" or "string to replace" is null, that replace will be ignored.
This will not repeat. For repeating replaces, call the overloaded
method.
Example 1
import org.apache.commons.lang3.StringUtils;
public class StringReplacer {
public static void main(String[] args) {
String input = "ab b test a b";
String output = StringUtils.replaceEach(input, new String[] { "a", "b", "tes" },
new String[] { "bhduh", "eieja", "neesj" });
System.out.println(input + " >>>> " + output);
}
}
Example 2
import org.apache.commons.lang3.StringUtils;
public class StringReplacer {
public static void main(String[] args) {
String input = "this is a test string with foo";
String output = StringUtils.replaceEach(input, new String[] { "a", "foo" },
new String[] { "foo", "bar"});
System.out.println(input + " >>>> " + output);
}
}
Try following:
Solution 1:
Traverse the String characters one by one and move the new String to a new StringBuffer or StringBuilder, then call toString() to get the result. This will need you to implement string matching algorithm.
Solution 2 (Using Regex):
For this, you must know the domain of your string. For example, it is [a-zA-Z] then other arbitrary characters (not part of domain) can be used for intermediate step. First replace the actual characters with arbitrary one then arbitrary ones with the target. In example below, [!##] are the arbitrary characters. These can be any random \uxxxx value as well.
String input = "a-b-c";
String output = input.replaceAll("[a]", "!").replaceAll("[b]", "#").replaceAll("[c]", "#");
output = output.replaceAll("[!]", "bcd").replaceAll("[#]", "cde").replaceAll("[#]", "def");
System.out.println("input: " + input);
System.out.println("Expected: bcd-cde-def");
System.out.println("Actual: " + output);
Your issue is quite common. To sum things up :
String test = "this is a test string with foo";
System.out.println(test.replace("a", "foo").replace("foo", "bar"));
Gives : this is bar test string with bar
Expected by you : this is foo test string with bar
You can use StrSubstitutor from Apache Commons Lang
But first you will have to inject placeholders in your string :
String test = "this is a test string with foo";
Map<String, String> valuesMap = new HashMap<>();
valuesMap.put("a", "foo");
valuesMap.put("foo", "bar");
String testWithPlaceholder = test;
// Preparing the placeholders
for (String value : valuesMap.keySet())
{
testWithPlaceholder = testWithPlaceholder.replace(value, "${"+value+"}");
}
And then, use StrSubstitutor
System.out.println(StrSubstitutor.replace(testWithPlaceholder, valuesMap));
It gives : this is foo test string with bar
Here is an method which is strictly just Java. I tried not to use any Java 8 methods here.
public static String translate(final String str, List<String> from, List<String> to, int index) {
StringBuilder components = new StringBuilder();
String token, replace;
int p;
if (index < from.size()) {
token = from.get(index);
replace = to.get(index);
p = 0;
for (int i = str.indexOf(token, p); i != -1; i = str.indexOf(token, p)) {
if (i != p) {
components.append(translate(str.substring(p, i), from, to, index + 1));
}
components.append(replace);
p = i + token.length();
}
return components.append(translate(str.substring(p), from, to, index + 1)).toString();
}
return str;
}
public static String translate(final String str, List<String> from, List<String> to) {
if (null == str) {
return null;
}
return translate(str, from, to, 0);
}
Sample test program
public static void main(String []args) {
String EnteredString = "aa hjkyu batesh a";
List<String> from = new ArrayList<>(Arrays.asList("a", "b", "tes"));
List<String> to = new ArrayList<>(Arrays.asList("bhduh", "eieja", "neesj"));
System.out.println(translate(EnteredString, from, to));
}
Output:
bhduhbhduh hjkyu eiejabhduhneesjh bhduh
Explaination
The algorithm is recursive, and it simply does the following
If a pattern found in the string matches a pattern in the from list
if there is any string before that pattern, apply the algorithm to that string
replace the found pattern with the corresponding pattern in the to list
append the replacement to the new string
discard the pattern in the from list and repeat the algorithm for the rest of the string
Otherwise append the rest of the string to the new string
You could use split like:
String[] pieces = jsonResponse.split("},{");
then you just parse the from and to in each piece and apply them with replace() then put the string back together again. (and please get your capitalization of your variables/methods right - makes it very hard to read the way you have it)
Apache Commons StringUtils::replaceEach does this.
String[] froms = new String[] {"a", "b"};
String[] tos = new String[] {"b","c"};
String result = StringUtils.replaceEach("ab", froms, tos);
// result is "bc"
Why not keep it very simple (if the JSON is always in same format, EG: from the same system). Instead of replacing from with to, replace the entire markup:
replace "from":"*from*" with "from":"*to*"
Why not just change the actual "to" and "from" labels? That way, you don't run into a situation where "bhudh" becomes "eieja". Just do a string replace on "from" and "to".

Check a particular string and delete part of string in android

I have a string format stored in shared preference. I would like to check if a particular word exists. If yes, then delete those few words which start from x and ends at y.
Something like this: For example:
String items = "Veggies=Beans-Carrot-Potato-Onions--DailyUse=Milk-Yogurt-Soap--Fruits=Apple-Banana-Grapes-Pears";
I would like to check if the above string items has "DailyUse=" if so delete all the words that are after "DailyUse=" until "--". So that my string looks like:
String Newitems = "Veggies=Beans-Carrot-Potato-Onions--Fruits=Apple-Banana-Grapes-Pears";
Is this possible? If so, how do I go about doing this?
Thanks!
Try this.
public static void main(String[] args) {
String items = "Veggies=Beans-Carrot-Potato-Onions--DailyUse=Milk-Yogurt-Soap--Fruits=Apple-Banana-Grapes-Pears";
String[] newItems = items.split("--");
System.out.println(newItems[0] + "--"+ newItems[2]);
}
I tried to put the DailyUse element in first, second and third position and this code seems to work. I think it can be improved, but here's an idea.
String items = "DailyUse=Milk-Yogurt-Soap--Veggies=Beans-Carrot-Potato-Onions--Fruits=Apple-Banana-Grapes-Pears";
String result = "";
if (items.contains("--DailyUse=")){ // not in first position
String[] a = items.split("--DailyUse=");
result = a[0];
if (a[1].contains("--")){ // Daily use is not the last element
String[] b = a[1].split("--");
result = result + "--" + b[1] ;
}
}
else if (items.contains("DailyUse=")){ // first position
String[] b = items.split("--");
result = items.replace(b[0]+"--", ""); // Delete the dailyuse part
}
Using regex
String [] tests = {
"DailyUse=Milk-Yogurt-Soap--Veggies=Beans-Carrot-Potato-Onions--DailyUse=Milk-Yogurt-Soap--Fruits=Apple-Banana-Grapes-Pears--DailyUse=Milk-Yogurt-Soap"
,"DailyUse=Milk-Yogurt-Soap"
,"DailyUse=Milk-Yogurt-Soap--DailyUse=Milk-Yogurt-Soap"
};
String key = "DailyUse";
for (String test : tests) {
String newItems = test;
// Replace only one at beginning
String regexp = "(^" + key + "=.+?(--|$))";
while(newItems.matches(regexp)) {
newItems = newItems.replaceAll(regexp, "");
}
// Regex to replace all other
regexp = "(--" + key + "=.+?)(--|$)";
newItems = newItems.replaceAll(regexp,"$2");
System.out.println("Before " + test);
System.out.println("After " + newItems);
}
UPDATE based on comments

How to remove matched words from end of String

I want to remove the following words from end of String ‘PTE’, ‘LTD’, ‘PRIVATE’ and ‘LIMITED’
i tried the code but then i stuck. i tried this
String[] str = {"PTE", "LTD", "PRIVATE", "LIMITED"};
String company = "Basit LTD";
for(int i=0;i<str.length;i++) {
if (company.endsWith(str[i])) {
int position = company.lastIndexOf(str[i]);
company = company.substring(0, position);
}
}
System.out.println(company.replaceAll("\\s",""));
It worked. But suppose the company is Basit LIMITED PRIVATE LTD PTE or Basit LIMITED PRIVATE PTE LTD or any combination of four words in the end. Then the above code just remove the last name i.e., PTE or PRIVATE and so on, and the output is BasitLIMITEDPRIVATELTD.
I want output to be just Basit
How can i do it?
Thanks
---------------Edit---
Please note here the company name is just an example, it is not necessary that it is always the same. may be i have name like
String company = "Masood LIMITED LTD PTE PRIVATE"
or any name that can have the above mentioned words at the end.
Thanks
You can do this in single line. no need to loop through. just use String#replaceAll(regex, str).
company = company.replaceAll("PTE$*?|LTD$*?|PRIVATE$*?|LIMITED$*?","");
If you place the unwanted words in the map it will be ommitted in the resultant string
HashMap map = new HashMap();
map.put("PTE", "");
map.put("LTD", "");
map.put("PRIVATE", "");
map.put("LIMITED", "");
String company = "Basit LTD PRIVATE PTE";
String words[] = company.split(" ");
String resultantStr = "";
for(int k = 0; k < words.length; k++){
if(map.get(words[k]) == null) {
resultantStr += words[k] + " ";
}
}
resultantStr = resultantStr.trim();
System.out.println(" Trimmed String: "+ resultantStr);
If you want to remove these suffixes only at the end of the string, then you could introduce a while loop:
String[] str = {"PTE", "LTD", "PRIVATE", "LIMITED"};
boolean foundSuffix = true;
String company = "Basit LTD";
while (foundSuffix) {
foundSuffix = false;
for(int i=0;i<str.length;i++) {
if (company.endsWith(str[i])) {
foundSuffix = true;
int position = company.lastIndexOf(str[i]);
company = company.substring(0, position);
}
}
}
System.out.println(company.replaceAll("\\s",""));
If you don't mind transforming PTE Basit LIMITED INC to Basit (and also remove the first PTE), then replaceAll should work, as explained by others.
I was trying to do exactly same thing for one of my projects. I wrote this code few days earlier. Now I was exactly trying to find a much better way to do it, that's how I found this Question. But after seeing other answers I decided to share my version of the code.
Collection<String> stopWordSet = Arrays.asList("PTE", "LTD", "PRIVATE", "LIMITED");
String company = "Basit LTD"; //Or Anything
String[] tokens = company.split("[\#\]\\\_\^\[\"\#\ \!\&\'\`\$\%\*\+\(\)\.\/\,\-\;\~\:\}\|\{\?\>\=\<]+");
Stack<String> tokenStack = new Stack<>();
tokenStack.addAll(Arrays.asList(tokens));
while (!tokenStack.isEmpty()) {
String token = tokenStack.peek();
if (stopWordSet.contains(token))
tokenStack.pop();
else
break;
}
String formattedCompanyName = StringUtils.join(tokenStack.toArray());
Try this :
public static void main(String a[]) {
String[] str = {"PTE", "LTD", "PRIVATE", "LIMITED"};
String company = "Basit LIMITED PRIVATE LTD PTE";
for(int i=0;i<str.length;i++) {
company = company.replaceAll(str[i], "");
}
System.out.println(company.replaceAll("\\s",""));
}
All you need is to use trim() and call your function recursively, Or each time you remove a sub string from the end, reset your i to 0.
public class StringMatchRemove {
public static void main(String[] args) {
String str="my name is noorus khan";
String search="noorus";
String newString="";
String word=str.replace(search," ");
StringTokenizer st = new StringTokenizer(word," ");
while(st.hasMoreTokens())
{
newString = newString + st.nextToken() + " ";
}
System.out.println(newString);
}
first using the replace method we get word=my name is ..... khan (Note: here(.) represents the space). Now we should have to remove these spaces for that we are creating a new string adding all the token simply.
Output: my name is khan

Why is Java String indexOf failing?

this must be quite simple but I am having great difficulty. You see I am trying to find a string within another string as follows.
e = input.indexOf("-->");
s = input.indexOf("<!--");
input = input.replace(input.substring(s, e + 3), " ");
The integers e and s are returning -1 in that it was not found and this is causing the replace method to fail. The test string I am using is "Chartered Certified<!--lol--> Accountants (ACCA)". I tried to creat a new string object and pass in the string as an argument as follows
e=input.indexOf(new String("<!--"));
This yielded the same result.
Any ideas ?
This is a stand alone piece of code I wrote and it works perfectly.
public static void main(String[] args) {
int e = 0;
int s = 0;
while (e != -1) {
//input.replace("\"", "\'");
e = input.indexOf("-->");
s = input.indexOf("<!--");
input = input.replace(input.substring(s, e + 3), " ");
e = input.indexOf("-->");
System.out.println(input);
}
}
But I cannot seem to see why it fails when i use this logic in my action class.
System.out.println("!Chartered Certified<!--lol--> Accountants (ACCA)".indexOf("-->"));
prints 27
So your input string must not be what you expect
String input = "Chartered Certified<!--lol--> Accountants (ACCA)";
int e = input.indexOf("-->");
int s = input.indexOf("<!--");
System.out.println(e+" "+s);
yields
26 19
so I think that there's an error somewhere else, is there other code in the middle?
The string "Chartered Certified Accountants (ACCA)" does not contain "-->" or "<!--", so e and s will always be -1.
Maybe you are obtaining the string from a sort of xml parser and hides the commented string on rendering. Check that the input string just before the indexOf call really has the '<!--' and '-->' strings inside.
I ran the test real quick using a command-line argument. It worked just fine. Here's the code/results:
public static void main(String[] args) {
String input = args[0];
System.out.println(input);
int e = input.indexOf("-->");
int s = input.indexOf("<!--");
input = input.replace(input.substring(s, e + 3), "");
System.out.println(input);
}
Output:
Chartered Certified<!--lol--> Accountants (ACCA)
Chartered Certified Accountants (ACCA)
If you were passing input as a command-line argument, make sure it is in quotes, or else input will be set to Chartered because of the spaces.
This code should work, there is some other problem. You should code it for safety though as shown below.
e = input.indexOf("-->");
s = input.indexOf("<!--");
if (e > -1 && s > -1 && e > s + 4) {
input = input.replace(input.substring(s, e + "-->".length()), " ");
}
Your code seems OK. So if it fails. it may be that the string it parses is not what you think it is. Where does the string come from? Try printing the string just before parsing it to see what it actually is.

Categories

Resources