Having an issue where I have a java string:
String aString="name==p==?header=hello?aname=?????lname=lastname";
I need to split on question marks followed by equals.
The result should be key/value pairs:
name = "=p=="
header = "hello"
aname = "????"
lname = "lastname"
The problem is aname and lname become:
name = ""
lname = "????lname=lastname"
My code simply splits by doing aString.split("\\?",2)
which will return 2 strings.One contains a key/value pair and the second string contains
the rest of the string. If I find a question mark in the string, I recurse on the second string to further break it down.
private String split(String aString)
{
System.out.println("Split: " + aString);
String[] vals = aString.split("\\?",2);
System.out.println(" - Found: " + vals.length);
for ( int c = 0;c<vals.length;c++ )
{
System.out.println(" - "+ c + "| String: [" + vals[c] + "]" );
if(vals[c].indexOf("?") > 0 )
{
split(vals[c]);
}
}
return ""; // For now return nothing...
}
Any ideas how I could allow a name of ?
Disclaimer: Yes , My Regex skills are very low, so I don't know if this could be done via a regex expression.
You can let regex do all the heavy lifting, first splitting your string up into pairs:
String[] pairs = aString.split("\\?(?!\\?)");
That regex means "a ? not followed by a ?", which gives:
[name==p==, header=hello, aname=????, lname=lastname]
To then also split the results into name/value, split only the first "=":
String[] split = pair.split("=", 2); // max 2 parts
Putting it all together:
String aString = "name==p==?header=hello?aname=?????lname=lastname";
for (String pair : aString.split("\\?(?!\\?)")) {
String[] split = pair.split("=", 2);
System.out.println(split[0] + " is " + split[1]);
}
Output:
name is =p==
header is hello
aname is ????
lname is lastname
You can try like this
String[] vals = "Hello??Man?HowAreYou????".split("\\?+");
System.out.println(vals[0]+vals[1]+vals[2]);
OUTPUT
HelloManHowAreYou
But as aname=????? you want to get you can replace the
????? Five Question Marks with Other Symbol and replace back to ????? after split
String processed="Hello????Good? ? ....???".replace("????","*");
OUTPUT
Hello*Good? ? ....???
And than use split for ?
Here the code, you are looking .
Implemented using the Split and HashMap.
Tested and Executed.
import java.util.HashMap;
import java.util.Map;
public class Sample {
public static void main(String[] args) {
// TODO Auto-generated method stub
// String[] vals = "Hello??Man?HowAreYou????".split("\\?+");
// System.out.println(vals[0]+vals[1]+vals[2]);
String query="name==p==?header=hello?aname=?????lname=lastname";
String[] params = query.split("\\?");
Map<String, String> map = new HashMap<String, String>();
for (String param : params)
{
String name = param.split("=")[0];
String value = param.substring(name.length(),param.length());
map.put(name, value);
System.out.println(name);
if(name.equals("")){
value+="?";
}
System.out.println(value.replaceAll(" ", ""));
}
}
}
I assume you are parsing URLs. The correct way would be to encode all special characters like ?, & and = which are values or names.
Better Solution: Encoding characters:
String name = "=p==";
String aname = "aname=????";
String lname = "lastname";
String url = "name=" + URLEncoder.encode(name, "UTF-8") +
"?aname=" + URLEncoder.encode(aname, "UTF-8") +
"?lname=" + URLEncoder.encode(lname, "UTF-8");
After that you have something like this:
name==p==?aname=?????lname=lastname
This can be splitted and decoded easily.
Other Solution: Bad input parsing:
If you insist, this works also. You can use a regex:
Pattern pattern = Pattern.compile("(\\w+?)=(\\S+?\\?+)");
Matcher m = pattern.matcher(query + "?");
while (m.find()) {
String key = m.group(1);
String value = m.group(2);
value = value.substring(0, value.length() - 1);
System.out.println(key + " = " +value);
}
Related
Say for instance I have this string:
"His name is Justin Hoffman"
and need to check if it is a valid name:
In order for this to return true I need to make sure I have "His name" before "is" and I need "Justin Hoffman" after the "is" how can I check to see if I have the correct substring before "is" and the correct one after "is"
String sentence = "His name is Justin Hoffman";
String[] splitSentence = sentence.split(" is ");
String first = splitSentence[0]; // His name
String second = splitSentence[1]; // Justin Hoffman
boolean isTrue = (first.equals("His name") && second.equals("Justin Hoffman"));
String input = "His name is Justin Hoffman";
String requiredFirstName = "His name";
String requiredLastName = "Justin Hoffman";
String delimiter = " is ";
// Example 1
if (input.equals(requiredFirstName + delimiter + requiredLastName))
{
System.out.println("The input is OK");
}
// Example 2
int posi = input.indexOf(delimiter);
if (posi > 0) // found
{
String leftPart = input.substring(0, posi);
String rightpart = input.substring(posi + delimiter.length());
if (requiredFirstName.equals(leftPart) && requiredLastName.equals(rightpart))
{
System.out.println("The input is OK");
}
}
// Example 3
String[] parts = input.split(delimiter);
if (requiredFirstName.equals(parts[0]) && requiredLastName.equals(parts[1]))
{
System.out.println("The input is OK");
}
The second example is possibly the fastest one because it does not produce temporary strings. The third example is the slowest one. Be careful with special character in the delimiter because the split() function interprets the argument as a regular expression.
Is there any solution on how to replace words in string without using String replace?
As you all can see this is like hard coded it. Is there any method to make it dynamically? I heard that there is some library file able to make it dynamically but I am not very sure.
Any expert out there able to give me some solutions? Thank you so much and have a nice day.
for (int i = 0; i < results.size(); ++i) {
// To remove the unwanted words in the query
test = results.toString();
String testresults = test.replace("numFound=2,start=0,docs=[","");
testresults = testresults.replace("numFound=1,start=0,docs=[","");
testresults = testresults.replace("{","");
testresults = testresults.replace("SolrDocument","");
testresults = testresults.replace("numFound=4,start=0,docs=[","");
testresults = testresults.replace("SolrDocument{", "");
testresults = testresults.replace("content=[", "");
testresults = testresults.replace("id=", "");
testresults = testresults.replace("]}]}", "");
testresults = testresults.replace("]}", "");
testresults = testresults.replace("}", "");
In this case, you will need learn regular expression and a built-in String function String.replaceAll() to capture all possible unwanted words.
For example:
test.replaceAll("SolrDocument|id=|content=\\[", "");
Simply create and use a custom String.replace() method which happens to use the String.replace() method within it:
public static String customReplace(String inputString, String replaceWith, String... stringsToReplace) {
if (inputString.equals("")) { return replaceWith; }
if (stringsToReplace.length == 0) { return inputString; }
for (int i = 0; i < stringsToReplace.length; i++) {
inputString = inputString.replace(stringsToReplace[i], replaceWith);
}
return inputString;
}
In the example method above you can supply as many strings as you like to be replaced within the stringsToReplace parameter as long as they are delimited with a comma (,). They will all be replaced with what you supply for the replaceWith parameter.
Here is an example of how it can be used:
String test = "This is a string which contains numFound=2,start=0,docs=[ crap and it may also "
+ "have numFound=1,start=0,docs=[ junk in it along with open curly bracket { and "
+ "the SolrDocument word which might also have ]}]} other crap in there too.";
testResult = customReplace(strg, "", "numFound=2,start=0,docs=[ ", "numFound=1,start=0,docs=[ ",
+ "{ ", "SolrDocument ", "]}]} ");
System.out.println(testResult);
You can also pass a single String Array which contains all your unwanted strings within its elements and pass that array to the stringsToReplace parameter, for example:
String test = "This is a string which contains numFound=2,start=0,docs=[ crap and it may also "
+ "have numFound=1,start=0,docs=[ junk in it along with open curly bracket { and "
+ "the SolrDocument word which might also have ]}]} other crap in there too.";
String[] unwantedStrings = {"numFound=2,start=0,docs=[ ", "numFound=1,start=0,docs=[ ",
"{ ", "SolrDocument ", "]}]} "};
String testResult = customReplace(test, "", unwantedStrings);
System.out.println(testResult);
I am writing a small programming language for a game I am making, this language will be for allowing users to define their own spells for the wizard entity outside the internal game code. I have the language written down, but I'm not entirely sure how to change a string like
setSpellName("Fireball")
setSplashDamage(32,5)
into an array which would have the method name and the arguments after it, like
{"setSpellName","Fireball"}
{"setSplashDamage","32","5"}
How could I do this using java's String.split or string regex's?
Thanks in advance.
Since you're only interested in the function name and parameters I'd suggest scanning up to the first instance of ( and then to the last ) for the params, as so.
String input = "setSpellName(\"Fireball\")";
String functionName = input.substring(0, input.indexOf('('));
String[] params = input.substring(input.indexOf(')'), input.length - 1).split(",");
To capture the String
setSpellName("Fireball")
Do something like this:
String[] line = argument.split("(");
Gets you "setSpellName" at line[0] and "Fireball") at line[1]
Get rid of the last parentheses like this
line[1].replaceAll(")", " ").trim();
Build your JSON with the two "cleaned" Strings.
There's probably a better way with Regex, but this is the quick and dirty way.
With String.indexOf() and String.substring(), you can parse out the function and parameters. Once you parse them out, apply the quotes are around each of them. Then combine them all back together delimited by commas and wrapped in curly braces.
public static void main(String[] args) throws Exception {
List<String> commands = new ArrayList() {{
add("setSpellName(\"Fireball\")");
add("setSplashDamage(32,5)");
}};
for (String command : commands) {
int openParen = command.indexOf("(");
String function = String.format("\"%s\"", command.substring(0, openParen));
String[] parameters = command.substring(openParen + 1, command.indexOf(")")).split(",");
for (int i = 0; i < parameters.length; i++) {
// Surround parameter with double quotes
if (!parameters[i].startsWith("\"")) {
parameters[i] = String.format("\"%s\"", parameters[i]);
}
}
String combine = String.format("{%s,%s}", function, String.join(",", parameters));
System.out.println(combine);
}
}
Results:
{"setSpellName","Fireball"}
{"setSplashDamage","32","5"}
This is a solution using regex, use this Regex "([\\w]+)\\(\"?([\\w]+)\"?\\)":
String input = "setSpellName(\"Fireball\")";
String pattern = "([\\w]+)\\(\"?([\\w]+)\"?\\)";
Pattern r = Pattern.compile(pattern);
String[] matches;
Matcher m = r.matcher(input);
if (m.find()) {
System.out.println("Found value: " + m.group(1));
System.out.println("Found value: " + m.group(2));
String[] params = m.group(2).split(",");
if (params.length > 1) {
matches = new String[params.length + 1];
matches[0] = m.group(1);
System.out.println(params.length);
for (int i = 0; i < params.length; i++) {
matches[i + 1] = params[i];
}
System.out.println(String.join(" :: ", matches));
} else {
matches = new String[2];
matches[0] = m.group(1);
matches[1] = m.group(2);
System.out.println(String.join(", ", matches));
}
}
([\\w]+) is the first group to get the function name.
\\(\"?([\\w]+)\"?\\) is the second group to get the parameters.
This is a Working DEMO.
I have two Strings, each one of them can be empty (blank or empty by StringUtils definition.) I need to display them in a concatenated fashion having a simple character in between, e.g. dash, comma, etc.
For example, a person's name consists of LastName and FirstName. PrintName method should print in this fashion:
case a: both not empty
print LastName + ", " FirstName
case b: FirstName is empty
print LastName
case c: LastName is empty
print FirstName
case d: both are empty
print empty string
This is just a simple exercise, but I'm curious if there's a most efficient method in Java that requires minimum variables/memory allocation, fewer lines of code, so on and so forth... My definition of efficiency is a bit vague so if you could write down why you think it's more efficient, that would be nice.
If it's just two strings, and they are empty, not null, I'd go with
System.out.println(
lastName
+ (( firstName.length() > 0 && lastName.length() > 0 ) ? ", " : "")
+ firstName
);
Explanation: the middle expression will be ", " only if both strings are non-empty.
In all other cases both the middle part and one or both of the others are empty. Thus, only the full side is printed.
If you want to go by StringUtils's definitions, the code is:
System.out.println(
StringUtils.stripToEmpty(lastName)
+ (( StringUtils.isNotBlank(firstName) && StringUtils.isNotBlank(lastName) ) ? ", " : "")
+ StringUtils.stripToEmpty(firstName)
);
You could design your pritning method like follows:
public class Main {
private final static Predicate<String> notEmpty = s -> s != null;
private final static Predicate<String> notBlank = s -> !s.equals("");
// ...
private static void printName(final String firstName, final String lastName) {
final boolean firstNameOk = notEmpty.and(notBlank).test(firstName);
final boolean lastNameOk = notEmpty.and(notBlank).test(lastName);
final StringBuilder result = new StringBuilder();
// Old version:
//result
// .append(lastNameOk ? lastName : "")
// .append(lastNameOk && firstNameOk ? ", " : "")
// .append(firstNameOk ? firstName : "");
// End of old Version:
// New version:
if (lastNameOk) {
result.append(lastName);
}
if (firstNameOk) {
if (lastNameOk) {
result.append(", ");
}
result.append(firstName);
}
// End of new version:
System.out.println(result);
}
}
Then some example calls:
public static void main(String[] args) {
printName("James", "Bond");
printName("James", null);
printName(null, "Bond");
printName(null, null);
}
Will print:
Bond, James
James
Bond
Only one boolean variable, but still four branches:
public void p(String f, String l) {
boolean e=l==null||l.isEmpty();
System.out.println(f==null||f.isEmpty()?e?"":l:e?f:f+", "+l);
}
This is surely not the best way and I would also recommend using Guava or another library like Apache commons.
return (firstName == null ? "" : firstname + ", " + lastName==null ? "" : lastName).replaceFirst("^, |, $","");
this will result in the firstname + ", " + lastname string, and in case the ", " string is at the beginning or the end of the string, it will be erased, therefore you get exactly what you want.
You can use apache commons api class to validate it in single line.
GenericValidator.isBlankOrNull(value);
For that you need to use apache commons jar and import this class
import org.apache.commons.validator.GenericValidator;
Try this one:
String LastName = "First";
String FirstName = "Last";
boolean cond1, cond2;
cond1 = FirstName == null || "".equals(FirstName);
cond2 = LastName == null || "".equals(LastName);
String DesiredName = (cond2 ? "" : LastName) +
((!cond2 && !cond1) ? ", " : "") +
(cond1 ? "" : FirstName);
System.out.println(DesiredName);
Use Google's guava and its Joiner method. It is the most elegant solution as far as I know.
https://code.google.com/p/guava-libraries/wiki/StringsExplained
Joiner joiner = Joiner.on(", ").skipNulls();
return joiner.join(firstName, lastName);
To skips nulls + empty strings, store firstName, lastName... in an array or list and then do
return Joiner.on(", ").join(Iterables.filter(listOfStrings, StringPredicates.notEmpty()));
You can look at the Joiner source code to see how its implemented. It is certainly not the most efficient but in this case the ignorable efficiency gain is worth trading off with code clarity and readability.
Clean, no extra conditions/libraries. This is of course specific to your requirement. You can use Guava's Joiner for more complex requirements.
public static void main(String[] args) throws Exception {
String firstName = "Stack";
String lastName = "Overflow";
System.out.println(printName(firstName, lastName));
}
private static String printName(String firstName, String lastName) {
StringBuilder buffer = new StringBuilder();
String cleanFirstName = avoidNull(firstName, "");
String cleanLastName = avoidNull(lastName, "");
if (!cleanLastName.isEmpty()) {
buffer.append(cleanLastName);
}
if (!cleanFirstName.isEmpty()) {
if (!cleanLastName.isEmpty()) {
buffer.append(", ");
}
buffer.append(cleanFirstName);
}
return buffer.toString();
}
private static String avoidNull(String str, String alternate) {
if (str == null || str.isEmpty()) {
return alternate;
}
return str;
}
You can remove the alternate parameter in the avoidNull() method if you don't want it.
private static String avoidNull(String str) {
return str == null ? "" : str;
}
I believe you shouldn't focus on performance this much, but on clean code.
If you have only two strings, you could create simple method as this one (I assume you are using Java 8).
public static String combine(String s1, String s2) {
StringJoiner sj = new StringJoiner(", ");
if (!StringUtils.isBlank(s1)) sj.add(s1);
if (!StringUtils.isBlank(s2)) sj.add(s2);
return sj.toString();
}
You can replace !StringUtils.isBlank(s1) with s1!=null %% !s1.trim().isEmpty()
If you want to create more generic method in which you could decide which delimiter to use, and which would be able to accept more than two Strings you could use something like
public static String joinWithourEmptyOrNull(String delimiter, String... words) {
StringJoiner sj = new StringJoiner(delimiter);
for (String s : words) {
if (!StringUtils.isBlank(s))
sj.add(s);
}
return sj.toString();
}
You can also rewrite this code into something more readable (at least for someone familiar with streams and lambdas - you don't have to be guru :D )
public static String joinWithourEmptyOrNull(String delimiter, String... words) {
return Arrays.stream(words)
.filter(s -> !StringUtils.isBlank(s))
.collect(Collectors.joining(delimiter));
}
Demo:
System.out.println(joinWithourEmptyOrNull(", ", "firstName", null, " ",
"secondName"));
result firstName, secondName
A simple "fix" would be
String toPrint = "";
if(lastName.length() > 0 && firstName.length() > 0){
toPrint = lastName + ", " - firstName;
}else if(!lastName.length() > 0 && firstName.length() > 0){
toPrint = firstName;
}else if(lastName.length() > 0 && !firstName.length() > 0){
toPrint = lastName;
}
System.out.println(toPrint)
I have a string like this
STAR=20110209
00:01:01|PNAM=test_.xml|PNUM=480|SSTA=20110209
00:01:01|STRT=20110209
00:01:01|STOP=20110209 00:01:01|
and i want to extract values of few of the keys here.
like whats the value of PNAM and SSTA.
I want a regular expression that can provide the values of few of the keys and keys can be in any order.
Would something like this work for you?
String str = "STAR=20110209 00:01:01|PNAM=test_.xml|PNUM=480|SSTA=20110209 00:01:01|STRT=20110209 00:01:01|STOP=20110209 00:01:01";
String[] parts = str.split("\\|");
for (String part : parts)
{
String[] nameValue = part.split("=");
if (nameValue[0] == "somekey")
{
// ..
}
}
So, the way your problem is really isn't best solved with regular expressions. Instead, use split() like someone else has offered, but instead of having a crazy if loop, load everything into a map.
String str = "STAR=20110209 00:01:01|PNAM=test_.xml|PNUM=480|SSTA=20110209 00:01:01|STRT=20110209 00:01:01|STOP=20110209 00:01:01";
String[] parts = str.split("|");
Map<String, String> properties = new HashMap<String, String>();
for (String part : parts) {
String[] nameValue = part.split("=");
properties.put(nameValue[0], nameValue[1]);
}
Then all you have to do is, properties.get("PNUM")
Use this Java code:
String str = "STAR=20110209 00:01:01|PNAM=test_.xml|PNUM=480|SSTA=20110209 00:01:01|STRT=20110209 00:01:01|STOP=20110209 00:01:01|";
Pattern p = Pattern.compile("([^=]*)=([^|]*)\\|");
Matcher m = p.matcher(str);
String pnamVal = null, sstaVal = null;
while (m.find()) {
//System.out.println("Matched: " + m.group(1) + '=' + m.group(2));
if (m.group(1).equals("PNAM"))
pnamVal = m.group(2);
else if (m.group(1).equals("SSTA"))
sstaVal = m.group(2);
if (pnamVal != null && sstaVal != null)
break;
}
System.out.println("SSTA: " + sstaVal);
System.out.println("PNAM: " + pnamVal);
OUTPUT
SSTA: 20110209 00:01:01
PNAM: test_.xml