simple mathematical expression parsing - java

I try to write equals override function. I think I have written right but the problem is that parsing the expression. I have an array type of ArrayList<String> it takes inputs from keyboard than evaluate the result. I could compare with another ArrayList<String> variable but how can I compare the ArrayList<String> to String. For example,
String expr = "(5 + 3) * 12 / 3";
ArrayList<String> userInput = new ArrayList<>();
userInput.add("(");
userInput.add("5");
userInput.add(" ");
userInput.add("+");
userInput.add(" ");
userInput.add("3");
.
.
userInput.add("3");
userInput.add(")");
then convert userInput to String then compare using equals
As you see it is too long when a test is wanted to apply.
I have used to split but It splits combined numbers as well. like 12 to 1 and 2
public fooConstructor(String str)
{
// ArrayList<String> holdAllInputs; it is private member in class
holdAllInputs = new ArrayList<>();
String arr[] = str.split("");
for (String s : arr) {
holdAllInputs.add(s);
}
}
As you expect it doesn't give the right result. How can it be fixed? Or can someone help to writing regular expression to parse it properly as wanted?
As output I get:
(,5, ,+, ,3,), ,*, ,1,2, ,/, ,3
instead of
(,5, ,+, ,3,), ,*, ,12, ,/, ,3

The Regular Expression which helps you here is
"(?<=[-+*/()])|(?=[-+*/()])"
and of course, you need to avoid unwanted spaces.
Here we go,
String expr = "(5 + 3) * 12 / 3";
.
. // Your inputs
.
String arr[] = expr.replaceAll("\\s+", "").split("(?<=[-+*/()])|(?=[-+*/()])");
for (String s : arr)
{
System.out.println("Element : " + s);
}
Please see my expiriment : http://rextester.com/YOEQ4863
Hope it helps.

Instead of splitting the input into tokens for which you don't have a regex, it would be good to move ahead with joining the strings in the List like:
StringBuilder sb = new StringBuilder();
for (String s : userInput)
{
sb.append(s);
}
then use sb.toString() later for comparison. I would not advice String concatenation using + operator details here.
Another approach to this would be to use one of the the StringUtils.join methods in Apache Commons Lang.
import org.apache.commons.lang3.StringUtils;
String result = StringUtils.join(list, "");
If you are fortunate enough to be using Java 8, then it's even easier...just use String.join
String result = String.join("", list);
More details on this approach available here

this makes all the inputs into one string which can then be can be compared against the expression to see if it is equal
String x = "";
for(int i = 0; i < holdAllInputs.length; i++){
x = x + holdAllInputs.get(i);
}
if(expr == x){
//do something equal
}else{
//do something if not equal
}

Related

how do you remove repeated strings in java?

Input: 3 3 2 1
Desired output: 3 2 1
(the spaces should remain)
I tried to use this method but it does not work
public String filterRepeats(String s)
{
return new LinkedHashSet<String(Arrays.asList(s.split("\\s"))).toString();
}
Your code works. If you are concerned about the brackets of the toString method. Just build a new string from the LinkedHashSet. For example:
public String filterRepeats(String s) {
LinkedHashSet<String> set = new LinkedHashSet<String>(Arrays.asList(s.split("\\s")));
String result = "";
for (String elt : set) {
result += elt + " ";
}
// trim last space
result = res2.substring(0, result.length()-1);
return result;
}
Caution! The below code is expensive, If you just need it work then you can do it in the below way.
String a = "a b c d a b c";
Set<String> foo = new LinkedHashSet<>(Arrays.asList(a.split(" ")));
a = foo.toString().replaceAll("\\[|\\]","").replaceAll(","," ");
If you are using Java 8, streams will simplify your job, you need not use the replaceAll method at all. Check the below statement.
a = foo.stream().collect(Collectors.joining(" "));
Cheers!

How to separate variables and arrays out of an expression with StringTokenizer?

I'm trying to separate the arrays and variables from an expression so that I can populate two ArrayLists with either array names or variables. I am using StringTokenizer. I have the expression broken down, but I am having trouble determining which tokens are array names and which are variables.
public void buildSymbols() {
String s = expr; // input from different part of the program
StringTokenizer st = new StringTokenizer(s, "+-*/[]() ");
while(st.hasMoreElements()){
String temp = st.nextToken();
System.out.println(temp);
}
}
I print temp just to make sure that the expression is being separated, but given an expression such as (varx + vary * varz[(vara + varb[(a + b) * 33])]) / 55 I don't know how to tell that varz and varb are array names, while varx, vary, vara, a, and b are variables.
Any ideas how to do this?
I agree wih EJP: The correct solution would be a specific parser. But if you would be content to recognize which delimitter was found by each call to StringTokenizer.nextToken, you can tell StringTokenizer to return also the delimitters. Also, you'll need to retrieve the next delimitter on every current token (as a lookahead). To do that, it's better to store all the tokens in a list:
public void buildSymbols() {
String s = expr; // input from different part of the program
StringTokenizer st = new StringTokenizer(s, "+-*/[]() ", true);
Set<String> delimiters=new HashSet<String>(Arrays.asList(new String[]{"+","-","*","/","[","]","(",")"," "}));
List<Object> tokens=Collections.list(st);
for(int i=0;i<tokens.size();i++){
String temp = tokens.get(i).toString();
if (delimiters.contains(temp))
{
// It is a delimiter
}
else
{
// It is a term
boolean isAnArray=(isNextTokenAnOpenBracket(tokens, i));
...
}
System.out.println(temp);
}
}
private boolean isNextTokenAnOpenBracket(List<Object> tokens, int currentIndex)
{
return (currentIndex < tokens.size() && "[".equals(tokens.get(1 + currentIndex)));
}
Try the String .split() method. It is an alternative to string tokenizer. You can split a string into an array of smaller strings split by a delimiter, just like StringTokenizer. However, you could do it two separate times, the first being with brackets, and the second with the other symbols. Then you know that the last index of your String arrays are the names of Arrays!
String s = expr;
String[] brackSplit = s.split("\\[");
for (String str : brackSplit) {
String[] finalSplit = str.split("*+-/()");
//finalSplit[finalSplit.length - 1] = Array Name!
}
NOTE: StringTokenizer is becoming deprecated with the new version of Java. The string split() method has become the new "recommended" way of splitting strings by delimiters.

what's a simple and elegant way to print arraylist elements separated by comma? [duplicate]

This question already has answers here:
A quick and easy way to join array elements with a separator (the opposite of split) in Java [duplicate]
(15 answers)
Closed 7 years ago.
Hi I'm writing code to print all elements from an ArrayList separated by comma, the folllowing is the method I wrote. It works. But i'm wondering if it can be simplified? And is there a more elegant way to print all elements from an ArrayList separated by some delimiter? (e.g. a method that prints an ArrayList of Strings get "Tom, Sherlock, Jack")
Thanks everyone!
public String printMyArrayList() {
if(mylist.size() == 0)return "";
else if(mylist.size() == 1)return mylist.get(0).toString();
else {
String returnStr = "";
for (int i = 0; i < mylist.size() ; i++) {
if(i == 0)returnStr = mylist.get(i).toString();
else {
returnStr = returnStr + ", " + mylist.get(i).toString();
}
}
return returnStr;
}
}
Using Collectors.joining from Java 8:
return list.stream()
.map(Object::toString)
.collect(Collectors.joining(", "));
Another Java 8 solution using String.join:
List<String> l = Arrays.asList(new String[] {"foo", "bar", "baz"});
String joined = String.join(", ", l);
System.out.println(joined);
Output:
foo, bar, baz
A one-liner.
System.out.println(myArrayList.toString().replaceAll("\\[\\]", ""));
I.e. get the default String representation (which is [1, 2, 3]) and remove the braces.
Try this:
String delimiter = "";
StringBuilder sb = new StringBuilder();
for (Item x : list) {
sb.append(delimiter).append(x);
delimiter = ",";
}
You can also use the Joiner class
Joiner.on(",").join(lst)
If you're working with android try this:
android.text.TextUtils.join(", ", listOfObjects);
else there's a util in spring framework.
org.springframework.util.StringUtils.arrayToCommaDelimitedString(listOfObjects);
Use List#toString method. It will enclose with []. If you don't want to include [] than you can substring it.
String listStr= list.toString();
String withoutSym= listStr.substring(1, listStr.length()-1);
I don't know what you mean by "simple and elegant", but I'll go with it.
EDIT: String.join is probably the best way
DOUBLE EDIT: Don't use this, as pointed out in the comments below.
public String printMyArrayList(ArrayList<String> list)
{
String result = "";
for(String s : list)
{
result += s + ", ";
}
return result.substring(0, result.length()-2);
}

Print array without brackets and commas

I'm porting a Hangman game to Android and have met a few problems. The original Java program used the console, so now I have to somehow beautify the output so that it fits my Android layout.
How do I print an array without the brackets and commas? The array contains slashes and gets replaced one-by-one when the correct letter is guessed.
I am using the usual .toString() function of the ArrayList class and my output is formatted like: [ a, n, d, r, o, i, d ]. I want it to simply print out the array as a single String.
I fill the array using this bit of code:
List<String> publicArray = new ArrayList<>();
for (int i = 0; i < secretWordLength; i++) {
hiddenArray.add(secretWord.substring(i, i + 1));
publicArray.add("-");
}
And I print it like this:
TextView currentWordView = (TextView) findViewById(R.id.CurrentWord);
currentWordView.setText(publicArray.toString());
Replace the brackets and commas with empty space.
String formattedString = myArrayList.toString()
.replace(",", "") //remove the commas
.replace("[", "") //remove the right bracket
.replace("]", "") //remove the left bracket
.trim(); //remove trailing spaces from partially initialized arrays
Basically, don't use ArrayList.toString() - build the string up for yourself. For example:
StringBuilder builder = new StringBuilder();
for (String value : publicArray) {
builder.append(value);
}
String text = builder.toString();
(Personally I wouldn't call the variable publicArray when it's not actually an array, by the way.)
For Android, you can use the join method from android.text.TextUtils class like:
TextUtils.join("",array);
first
StringUtils.join(array, "");
second
Arrays.asList(arr).toString().substring(1).replaceFirst("]", "").replace(", ", "")
EDIT
probably the best one: Arrays.toString(arr)
With Java 8 or newer, you can use String.join, which provides the same functionality:
Returns a new String composed of copies of the CharSequence elements joined together with a copy of the specified delimiter
String[] array = new String[] { "a", "n", "d", "r", "o", "i", "d" };
String joined = String.join("", array); //returns "android"
With an array of a different type, one should convert it to a String array or to a char sequence Iterable:
int[] numbers = { 1, 2, 3, 4, 5, 6, 7 };
//both of the following return "1234567"
String joinedNumbers = String.join("",
Arrays.stream(numbers).mapToObj(String::valueOf).toArray(n -> new String[n]));
String joinedNumbers2 = String.join("",
Arrays.stream(numbers).mapToObj(String::valueOf).collect(Collectors.toList()));
The first argument to String.join is the delimiter, and can be changed accordingly.
If you use Java8 or above, you can use with stream() with native.
publicArray.stream()
.map(Object::toString)
.collect(Collectors.joining(" "));
References
Use Java 8 Language Features
JavaDoc StringJoiner
Joining Objects into a String with Java 8 Stream API
the most simple solution for removing the brackets is,
convert the arraylist into string with .toString() method.
use String.substring(1,strLen-1).(where strLen is the length of string after conversion from arraylist).
the result string is your string with removed brackets.
I have used
Arrays.toString(array_name).replace("[","").replace("]","").replace(", ","");
as I have seen it from some of the comments above, but also i added an additional space character after the comma (the part .replace(", ","")), because while I was printing out each value in a new line, there was still the space character shifting the words. It solved my problem.
I used join() function like:
i=new Array("Hi", "Hello", "Cheers", "Greetings");
i=i.join("");
Which Prints:
HiHelloCheersGreetings
See more: Javascript Join - Use Join to Make an Array into a String in Javascript
String[] students = {"John", "Kelly", "Leah"};
System.out.println(Arrays.toString(students).replace("[", "").replace("]", " "));
//output: John, Kelly, Leah
You can use the reduce method provided for streams for Java 8 and above.Note you would have to map to string first to allow for concatenation inside of reduce operator.
publicArray.stream().map(String::valueOf).reduce((a, b) -> a + " " + b).get();
I was experimenting with ArrayList and I also wanted to remove the Square brackets after printing the Output and I found out a Solution. I just made a loop to print Array list and used the list method " myList.get(index) " , it works like a charm.
Please refer to my Code & Output below:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
ArrayList mylist = new ArrayList();
Scanner scan = new Scanner(System.in);
for(int i = 0; i < 5; i++) {
System.out.println("Enter Value " + i + " to add: ");
mylist.add(scan.nextLine());
}
System.out.println("=======================");
for(int j = 0; j < 5; j++) {
System.out.print(mylist.get(j));
}
}
}
OUTPUT
Enter Value 0 to add:
1
Enter Value 1 to add:
2
Enter Value 2 to add:
3
Enter Value 3 to add:
4
Enter Value 4 to add:
5
=======================
12345
Just initialize a String object with your array
String s=new String(array);

Remove last set of value from a comma separated string in java

I wan to remove the last set of data from string using java.
For example I have a string like A,B,C, and I want to remove ,C, and want to get the out put value like A,B . How is it possible in java? Please help.
String start = "A,B,C,";
String result = start.subString(0, start.lastIndexOf(',', start.lastIndexOf(',') - 1));
Here is a fairly "robust" reg-exp solution:
Pattern p = Pattern.compile("((\\w,?)+),\\w+,?");
for (String test : new String[] {"A,B,C", "A,B", "A,B,C,",
"ABC,DEF,GHI,JKL"}) {
Matcher m = p.matcher(test);
if (m.matches())
System.out.println(m.group(1));
}
Output:
A,B
A
A,B
ABC,DEF,GHI
Since there may be a trailing comma, something like this (using org.apache.commons.lang.StringUtils):
ArrayList<String> list = new ArrayList(Arrays.asList(myString.split()));
list.remove(list.length-1);
myString = StringUtils.join(list, ",");
You can use String#lastIndexOf to find the index of the second-to-last comma, and then String#substring to extract just the part before it. Since your sample data ends with a ",", you'll need to use the version of String#lastIndexOf that accepts a starting point and have it skip the last character (e.g., feed in the string's length minus 1).
I wasn't going to post actual code on the theory better to teach a man to fish, but as everyone else is:
String data = "A,B,C,";
String shortened = data.substring(0, data.lastIndexOf(',', data.length() - 2));
You can use regex to do this
String start = "A,B,C,";
String result = start.replaceAll(",[^,]*,$", "");
System.out.println(result);
prints
A,B
This simply erases the the 'second last comma followed by data followed by last comma'
If full String.split() is not possible, the how about just scanning the string for comma and stop after reaching 2nd, without including it in final answer?
String start = "A,B";
StringBuilder result = new StringBuilder();
int count = 0;
for(char ch:start.toCharArray()) {
if(ch == ',') {
count++;
if(count==2) {
break;
}
}
result.append(ch);
}
System.out.println("Result = "+result.toString());
Simple trick, but should be efficient.
In case you want last set of data removed, irrespective of how much you want to read, then
start.substring(0, start.lastIndexOf(',', start.lastIndexOf(',')-1))
Another way to do this is using a StringTokenizer:
String input = "A,B,C,";
StringTokenizer tokenizer = new StringTokenizer(input, ",");
String output = new String();
int tokenCount = tokenizer.countTokens();
for (int i = 0; i < tokenCount - 1; i++) {
output += tokenizer.nextToken();
if (i < tokenCount - 1) {
output += ",";
}
}
public string RemoveLastSepratorFromString(string input)
{
string result = input;
if (result.Length > 1)
{
result = input.Remove(input.Length - 1, 1);
}
return result;
}
// use from above method
string test = "1,2,3,"
string strResult = RemoveLastSepratorFromString(test);
//output --> 1,2,3

Categories