Simple Logic or Regex Expresssion for a string - java

Hi I've a string like the following -
name,number,address(line1,city),status,contact(id,phone(number,type),email(id),type),closedate
I need to output the following -
name,number,address.line1,address.city,status,contact.id,contact.phone.number,contact.phone.type,contact.email.id,contact.type,closedate
Is it possible to do it using regex in java. Logic I have thought of is using string manipulation (with substring,recursion etc). Is there a simple way of achieving this? I would prefer a regular expression which works in java. Other suggestions are also welcome.
To give you a context
The string above is coming as query parameter, I have to find out what all columns I need to select based on that. so all these individual items in the output will have a respective column name in property file.
Thanks
Pal

public class Main {
public static void main(String[] args) {
;
String input ="name,number,address(line1,test(city)),status,contact(id,phone(number,type),email(id),type),closedate";
List<String> list = new ArrayList<String>(Arrays.asList(input.split(","))); // We need a list for the iterator (or ArrayIterator)
List<String> result = new Main().parse(list);
System.out.println(String.join(",", result));
}
private List<String> parse(List<String> inputString){
Iterator<String> it = inputString.iterator();
ArrayList<String> result = new ArrayList<>();
while(it.hasNext()){
String word = it.next();
if(! word.contains("(")){
result.add(word);
} else { // if we come across a "(", start the recursion and parse it till we find the matching ")"
result.addAll(buildDistributedString(it, word,""));
}
}
return result;
}
/*
* recursivly parse the string
* #param startword The first word of it (containing the new prefix, the ( and the first word of this prefic
* #param prefix Concatenation of previous prefixes in the recursion
*/
private List<String> buildDistributedString(Iterator<String> it, String startword,String prefix){
ArrayList<String> result = new ArrayList<>();
String[] splitted = startword.split("\\(");
prefix += splitted[0]+".";
if(splitted[1].contains(")")){ //if the '(' is immediately matches, return only this one item
result.add(prefix+splitted[1].substring(0,splitted[1].length()-1));
return result;
} else {
result.add(prefix+splitted[1]);
}
while(it.hasNext()){
String word = it.next();
if( word.contains("(")){ // go deeper in the recursion
List<String> stringList = buildDistributedString(it, word, prefix);
if(stringList.get(stringList.size()-1).contains(")")){
// if multiple ")"'s were found in the same word, go up multiple recursion levels
String lastString = stringList.remove(stringList.size()-1);
stringList.add(lastString.substring(0,lastString.length() -1));
result.addAll(stringList);
break;
}
result.addAll(stringList);
} else if(word.contains(")")) { // end this recursion level
result.add(prefix + word.substring(0,word.length()-1)); // ")" is always the last char
break;
} else {
result.add(prefix+word);
}
}
return result;
}
}
I wrote a quick parser for this. There probably are some improvements possible, but this should give you an idea. It was just meant to get a working version asap.

Since nested parentheses appear in your string, regular expressions can't do the job. The explanation why is complicated, requiring knowledge in context free grammars. See Can regular expressions be used to match nested patterns?
I've heard this kind of parsing can be done through callbacks, but I believe it doesn't exist in Java.
Parser generators like JavaCC would do the job, but that's a huge overkill for the task you are describing.
I recommend you to look into java.util.Scanner, and you recursively call the parse method whether you see a left paren.

Related

Get the Smallest Matching String from a Long String

Suppose I have a String
interpreter, interprete, interpret
now what i want to do is to get the smallest matching string from the above string that must be:
interpret
Is it possible using Java if it is can somebody help me out digging this problem thanks
Check out this.....
public static void main(String[] ar)
{
List<String> all=new LinkedList<String>();
all.add("interpreter");
all.add("interprete");
all.add("interpret");
String small="";
small=all.get(0);
for (String string : all) {
if(small.contains(string))
{
small=string;
}
}
System.out.println(small);
}
Let me know, Is it satisfying your requirement???
//-----------------Edited One--------------------------
public static void main(String[] ar)
{
List<String> all=new LinkedList<String>();
Set<String> result=new LinkedHashSet<String>();
all.add("interpreter");
all.add("interprete");
all.add("interpret");
all.add("developed");
all.add("develops");
String small="";
for(int i=0;i<all.size();i++)
{
small=all.get(i);
for(int j=i;j<all.size();j++)
{
if(small.contains(all.get(j)))
{
small=all.get(j);
}
}
result.add(small);
}
for (String string : result) {
System.out.println(string);
}
}
If I get you correctly, you want the shortest word in an input string s which includes a target string t="interpret".
So first, split the string into words w, e.g., using s.split("\\s*,\\s*"), then use w.contains(t) on each string w to check if it contains the word you look for. Choose the shortest string for which the contains method returns true.
you need to compare all char one by one of all string and a array of boolean flag maintain
for every pair of string then check out all Boolean array similarity(length) and then substring
of any string from that length
i hope this will help
What you are looking for is called a lemmatizer/steamer for Java.
There are a few of them (I have not used any) but you may want to search/try a few of them:
Snowball
Lemamatization
You should test each of them, because for example some (in case of snowball) will do:
Community
Communities --> Communiti // this is obviously wrong

java startsWith() method with custom rules

I implement typing trainer and would like to create my special String startsWith() method with specific rules.
For example: '-' char should be equal to any long hyphen ('‒', etc). Also I'll add other rules for special accent characters (e equals é, but not é equals e).
public class TestCustomStartsWith {
private static Map<Character, List<Character>> identityMap = new HashMap<>();
static { // different hyphens: ‒, –, —, ―
List<Character> list = new LinkedList<>();
list.add('‒');
list.add('–'); // etc
identityMap.put('-', list);
}
public static void main(String[] args) {
System.out.println(startsWith("‒d--", "-"));
}
public static boolean startsWith(String s, String prefix) {
if (s.startsWith(prefix)) return true;
if (prefix.length() > s.length()) return false;
int i = prefix.length();
while (--i >= 0) {
if (prefix.charAt(i) != s.charAt(i)) {
List<Character> list = identityMap.get(prefix.charAt(i));
if ((list == null) || (!list.contains(s.charAt(i)))) return false;
}
}
return true;
}
}
I could just replace all kinds of long hyphens with '-' char, but if there will be more rules, I'm afraid replacing will be too slow.
How can I improve this algorithm?
I don't know all of your custom rules, but would a regular expression work?
The user is passing in a String. Create a method to convert that String to a regex, e.g.
replace a short hyphen with short or long ([-‒]),
same for your accents, e becomes [eé]
Prepend with the start of word dohicky (\b),
Then convert this to a regex and give it a go.
Note that the list of replacements could be kept in a Map as suggested by Tobbias. Your code could be something like
public boolean myStartsWith(String testString, String startsWith) {
for (Map.Entry<String,String> me : fancyTransformMap) {
startsWith = startsWith.replaceAll(me.getKey(), me.getValue());
}
return testString.matches('\b' + startsWith);
}
p.s. I'm not a regex super-guru so if there may be possible improvements.
I'd think something like a HashMap that maps the undesirable characters to what you want them to be interpreted as might be the way to go if you are worried about performance;
HashMap<Character, Character> fastMap = new Map<Character, Character>();
// read it as '<long hyphen> can be interpreted as <regular-hyphen>
fastMap.add('–', '-');
fastMap.add('é', 'e');
fastMap.add('è', 'e');
fastMap.add('?', '?');
...
// and so on
That way you could ask for the value of the key: value = map.get(key).
However, this will only work as long as you have unique key-values. The caveat is that é can't be interpreted as è with this method - all the keys must be unique. However, if you are worried about performance, this is an exceedingly fast way of doing it, since the lookup time for a HashMap is pretty close to being O(1). But as others on this page has written, premature optimization is often a bad idea - try implementing something that works first, and if at the end of it you find it is too slow, then optimize.

Should the toString() method be added?

This is the piece of code.
List<BDDObject> childlist = savingObject.getChildren("TherapyAreaReference");
if (childlist.size() > 1) {
for (int i = 0; i < childlist.size() - 1; i++) {
String newMedcondRefChild = ((String) childlist
.get(i)
.getValue( IDDConstants.IDD_THERAPY_AREA_REF_VALUE))
.toLowerCase()
.trim()
.concat(((String) childlist
.get(i)
.getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME))
.toLowerCase().trim());
}
}
IDDConstants has public static final strings defined in it. As StringBuffer is more effective, how can it be incorporated for the concat operations?
I'm guessing that the intention is to generate a list of 'reports', one for each BDDObject record found. Based on that idea, your code should look more like this:
public List<String> getReport(List<BDDObject> records) {
List<String> reports = new ArrayList<String>(record.size());
for (BDDObject record:records) {
String newMedcondRefChild = String.valueOf(record.getValue( IDDConstants.IDD_THERAPY_AREA_REF_VALUE))
.toLowerCase()
.trim() + String.valueOf(record.getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME)))
.toLowerCase().trim());
reports.add(newMedcondRefChild);
}
return reports;
}
Regarding the question on whether toString() would be helpful, the only place where I see it fitting, would be on the BDDObject itself. It would look something like this:
class BDDObject {
...
#Override
public String toString() {
return String.valueOf(getValue(IDDConstants.IDD_THERAPY_AREA_REF_VALUE)).toLowerCase().trim() +
String.valueOf(getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME)).toLowerCase().trim());
}
In which case, the function to create the report becomes trivial:
public List<String> getReport(List<BDDObject> records) {
List<String> reports = new ArrayList<String>(record.size());
for (BDDObject record:records) {
reports.add(record.toString());
}
return reports;
}
In case that what you want is a looooong string with all the values concatenated to it, you can use StringBuilder, like this:
public String getReport(List<BDDObject> records) {
StringBuilder sb = new StringBuilder();
for (BDDObject record:records) {
sb.append(String.valueOf(record.getValue( IDDConstants.IDD_THERAPY_AREA_REF_VALUE))
.toLowerCase()
.trim());
sb.append(String.valueOf(record.getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME))
.toLowerCase().trim()));
}
return sb.toString();
}
This will return all the records appended after each other. I doubt its readability, but you I hope you get the idea. StringBuilder is helpful when you need to build a string iteratively (like in the previous example). StringBuilder should not be used to replace single String operations like : String a = b.get() + c.get(); given that the compiler implicitly creates a StringBuilder in these cases and therefore there's no actual performance improvement to be achieved.
In the code in your question, StringBuffer/StringBuilder will not give you any performance gains, because you concatenate only two strings. However, the question does not state what you are doing with the string in newMedconfRefChild. If your actual goal is to concatenate the strings of each loop iteration, then you should use a StringBuilder (use StringBuffer only when it is really necessary, prefer StringBuilder).

Is there a way to replace all occurrences of a string in a variable of a list?

I have a list as follows
List<Summary> summary;
Summary {
int key;
String value1;
String value2;
}
Is there a way in java (or any other utility library) to replace all occurrences of a String "String1" in the variable value1 without having to loop through the list?
Looping the list is inevitable so you or some third party library has to do the looping. Is it really that hard to do:
for (Summary s : summary)
if (s.value1.equals("String1"))
s.value1 = "...";
? :)
Maybe you could use a library that allow you use it without loops, the problem is that in the low level the compiler must use something like a loop for do it.
I think that direct or indirectly you will use a loop.
So, for this reason you haven´t any problem if use a loop in your code.
Sorry for my English, I hope you can understand all.
You can add a method to find by the object part:
public class ListOfString {
public static void main(String[] args) {
List<Model> models = new ArrayList<>();
for(int i = 0 ; i < 5; i++) {
Model model = new Model();
model.setStr("String"+i);
models.add(model);
}
Model temp = new Model();
temp.setStr("String1");
System.out.println(containsObjectPart(temp, models));
}
// This method just a prototype, you can modify as you like...
private static boolean containsObjectPart(Model obj, List<Model> models) {
for(Model model : models) {
if(model.getStr().equals(obj.getStr()))
return true;
}
return false;
}
}
class Model {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
No you cannot, Loop is invetible.But you can optimize it many area like, selecting loop, how do you find the string and replacing it .etc....
You could avoid a bit of looping - at the expense of losing your list ordering - by using a TreeSet, with value1 values as keys and the Summary objects as values. Then you can do a binary chop search to find all matching entries. A collection which uses hashing would have similar trade-offs and gains.
Otherwise, as everyone else has said, looping is inevitable. The only optimisation you could make is counting the entries as they go into the list so you know when you've found them all so you can stop looping.
But remember, premature optimisation is the root of all evil. :)

Java math expression parser that can take complex numbers as a variable?

I am writing a program in Processing that transforms complex numbers. However, I want to have a method of taking an input string and calculating the transformation using a complex variable. For example:
1/(z+1)
(z^2)/(z/2)
where z is a complex number. Now, I've looked at JEP and some examples, but I cannot work out if it would allow you to actually enter z as a variable (and in any case it is not free). Is there an expression parser for Java (that works in processing, which uses an old version of java and does not have generics) that I could use to do this?
If there is not, could someone point me to the basics of how to create one?
As mentioned by PhiLo, you can use generics. Try this Processing sketch:
import java.util.*;
java.util.List<String> list = Arrays.asList("a", "b", "c");
textFont(loadFont("UMingCN-30.vlw"));
for(int i = 0; i < list.size(); i++) {
text(list.get(i), 5, int(i*30)+30);
}
And there's a non commercial version of JEP available (GPL). Download it here and add it to your Processing classpath (import it).
After successfully doing so, you can use JEP like this:
void setup() {
org.nfunk.jep.JEP parser = new org.nfunk.jep.JEP();
parser.addComplex();
try {
parser.parseExpression("(1+2*i) + (3+8*i)");
println(parser.getComplexValue());
} catch(Exception e) {
e.printStackTrace();
}
}
which produces the (expected) output: (4.0, 10.0)
Have a look at this: http://bracer.sourceforge.net It's my implementation of shunting-yard algorithm and this parser supports complex numbers.
Use Apache Common Math. It is very easy to use.
You can initialize both real+imaginary parts. You can also initialize them from a string. It supports a wide array of operations that you can do with imaginary numbers.
Here is a example of code for doing some common operations:
package complex;
import static java.lang.String.format;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.complex.ComplexFormat;
public class Do
{
public static void main(String[] args)
{
ComplexFormat format = new ComplexFormat();
Complex lhs = new Complex(1.0, 3.0);
Complex rhs = new Complex(2.0, 5.0);
Complex answer = lhs.add(rhs); // add two complex numbers
System.out.println("Add : "+ format.format(answer));
answer = lhs.subtract(rhs); // subtract two complex numbers
System.out.println("Subtract : "+ format.format(answer));
answer = lhs.conjugate();
System.out.println("Conjgate : "+ format.format(answer));
double d = lhs.abs();
System.out.println("Absolute : "+d);
Complex first = new Complex(1.0, 3.0);
Complex second = new Complex(2.0, 5.0);
answer = first.log(); // natural logarithm.
System.out.println("Logarithm : "+ format.format(answer));
answer = first.cos(); // cosine
System.out.println("Cosine : "+ format.format(answer));
answer = first.pow(second); // first raised to the power of second
System.out.println("Power : "+ format.format(answer));
Complex z = new Complex(2.0,2.0);
Complex z1 = z.reciprocal();
System.out.println("Recipocal : "+ format.format(z1));
System.out.println("Absoltue of 2+2i is "+z.abs());
System.out.println("Argument of 2+2i is "+z.getArgument());
Complex r = new Complex(6.3,9.6);
String conj = format.format(r.conjugate());
String reci = format.format(r.reciprocal());
System.out.println("Conjugate : "+conj+" Recipocal : "+reci);
//answer = lhs.abs(); // absolute value
//answer = lhs.conjugate(rhs); // complex conjugate
//make complex to string
ComplexFormat format = new ComplexFormat(); // default format
Complex c = new Complex(1.1111, 2.2222);
String s = format.format(c); // s contains "1.11 + 2.22i"
System.out.println(s);
//make string to complex
String z = "2.5+3.6i";
Complex e = format.parse(z);
System.out.println(e);
}
}
Another alternative is FrAid, if you want another option.
If for some reason you need more flexibility than the "canned" complex math expression parsers suggested so far (= full control over operators, precedence, tree construction), you may want to consider my configurable parser:
https://github.com/stefanhaustein/expressionparser
Example direct evaluation code for your case:
static HashMap<String, Complex> variables = new HashMap<>();
/**
* Processes the calls from the parser directly to a Complex value.
*/
static class ComplexProcessor extends ExpressionParser.Processor<Complex> {
#Override
public Complex infixOperator(ExpressionParser.Tokenizer tokenizer, String name, Complex left, Complex right) {
switch (name.charAt(0)) {
case '+': return left.plus(right);
case '-': return left.minus(right);
case '*': return left.times(right);
case '/': return left.divides(right);
case '^':
if (right.im() != 0 || right.re() == (int) right.re()) {
return left.pow((int) right.re());
}
throw new RuntimeException("Only integer exponents supported by Complex.pow().");
default:
throw new IllegalArgumentException();
}
}
#Override
public Complex prefixOperator(ExpressionParser.Tokenizer tokenizer, String name, Complex argument) {
return name.equals("-") ? new Complex(0,0).minus(argument) : argument;
}
#Override
public Complex numberLiteral(ExpressionParser.Tokenizer tokenizer, String value) {
return new Complex(Double.parseDouble(value), 0);
}
#Override
public Complex identifier(ExpressionParser.Tokenizer tokenizer, String name) {
Complex value = variables.get(name);
if (value == null) {
throw new IllegalArgumentException("Undeclared variable: " + name);
}
return value;
}
#Override
public Complex group(ExpressionParser.Tokenizer tokenizer, String paren, List<Complex> elements) {
return elements.get(0);
}
/**
* Creates a parser for this processor with matching operations and precedences set up.
*/
static ExpressionParser<Complex> createParser() {
ExpressionParser<Complex> parser = new ExpressionParser<Complex>(new ComplexProcessor());
parser.addCallBrackets("(", ",", ")");
parser.addGroupBrackets("(", null, ")");
parser.addOperators(ExpressionParser.OperatorType.INFIX_RTL, 4, "^");
parser.addOperators(ExpressionParser.OperatorType.PREFIX, 3, "+", "-");
// 2 Reserved for implicit multiplication
parser.addOperators(ExpressionParser.OperatorType.INFIX, 1, "*", "/");
parser.addOperators(ExpressionParser.OperatorType.INFIX, 0, "+", "-");
return parser;
}
}
Example invocation:
variables.put("i", new Complex(0, 1));
variables.put("z", new Complex(1, 1));
ExpressionParser<Complex> parser = ComplexProcessor.createParser();
System.out.println("(z^2)/(z/2):", parser.parse("(z^2)/(z/2)"));
The parser itself is implemented in a single java file without dependencies, so for evaluation purposes it's simple to copy to your own project
I would (and have, actually) manually make a parse table and use a simple LR or LALR parser to process it. At a reduction, you can perform the calculations. One advantage to this is that it is easy to modify the "language", or acceptable input.
Here's crazy solution: java has built-in JavaScript engine (I suppose you can access it from Processing). Now, you write a javascript class that works with complex numbers(copy it from here). Then, overload math operators as specified here. AFter that you can just eval this string from java. It's crazy and I'm not sure that it will work (i don't know javascript). Maybe it will make to find some simplier solution without parsing expressions.
Here is a link to a straight-forward math expression parser (64 lines): http://javadots.blogspot.com/2008/11/arithemetic-expressions-solver-in-64.html
Tweaking it to support your needs should not be too difficult

Categories

Resources