Related
I'm trying to develop a function that reads an ArrayList of string and is capable to find if there exist at least two tuples that have the same values from a set of indices but differ for a supplementary index. I've developed a version of this function by using a RegEx comparison as follow:
public boolean checkMatching(){
ArrayList<String> rows = new ArrayList<String>();
rows.add("7,2,2,1,1");
rows.add("7,3,2,1,1");
rows.add("7,8,1,1,1");
rows.add("8,2,1,3,1");
rows.add("8,2,1,4,1");
rows.add("8,4,5,1,1");
int[] indices = new int[] {2,3};
int supplementaryIndex = 1;
String regex = "";
for(String r : rows){
String[] rt = r.split(",");
regex = "[a-zA-Z0-9,-.]*[,][a-zA-Z0-9,-.]*[,][" + rt[indices[0]] + "][,][" + rt[indices[1]] + "][,][a-zA-Z0-9,-.]*";
for(String r2 : rows){
if(r.equals(r2) == false){
if(Pattern.matches(regex, r2)){
String[] rt2 = r.split(",");
if(rt[supplementaryIndex].equals(rt2[supplementaryIndex]) == false){
return true;
}
}
}
}
}
return false;
}
However, it is very expensive, especially if there are many rows. I've thought to create a more complex RegEx that considers multiple choices (with '|' condition), as follow:
public boolean checkMatching(){
ArrayList<String> rows = new ArrayList<String>();
rows.add("7,2,2,1,1");
rows.add("7,3,2,1,1");
rows.add("7,8,1,1,1");
rows.add("8,2,1,3,1");
rows.add("8,2,1,4,1");
rows.add("8,4,5,1,1");
int[] indices = new int[] {2,3};
int supplementaryIndex = 1;
String regex = "";
for(String r : rows){
String[] rt = r.split(",");
regex += "[a-zA-Z0-9,-.]*[,][a-zA-Z0-9,-.]*[,][" + rt[indices[0]] + "][,][" + rt[indices[1]] + "][,][a-zA-Z0-9,-.]*";
regex += "|"; //or
}
for(String r2 : rows){
if(Pattern.matches(regex, r2)){
//String rt2 = r.split(",");
//if(rt[supplementaryIndex].equals(rt2[supplementaryIndex]) == false){
return true;
//}
}
}
return false;
}
But the problem is that this way I can't compare the supplementary index values. Do you have any suggestions on how to define a regex that can directly satisfy this condition? Or, is it possible to leverage java streams to do this efficiently?
The main problem of your first approach is that you have two nested loops over the same list, which gets you a quadratic time complexity. To recall, that implies that the inner loop’s body gets executed 10,000 times for a list with 100 elements and 1,000,000 times for a list of 1,000 elements, and so on.
It doesn’t help calling Pattern.matches(regex, r2) in the inner loop’s body. That method exist only to support (as delegation target) the String operation r2.matches(r2), a convenience method, to do Pattern.compile(regex).matcher(input).matches() in one go. If you have to apply the same regex multiple times, you should keep and re-use the result of Pattern.compile(regex).
But here, there is no point in using a regex at all. You have already decomposed the string using split and can access each component via a plain array access. Using this starting point to compose a regex to be applied on the string again, is complicated and expensive at the same time.
Just use something like
// return true when at least one string has the same values for indices
// but different value for supplementaryIndex
Map<List<String>,String> map = new HashMap<>();
for(String r : rows) {
String[] rt = r.split(",");
List<String> key = List.of(rt[indices[0]], rt[indices[1]]);
String old = map.putIfAbsent(key, rt[supplementaryIndex]);
if(old != null && !old.equals(rt[supplementaryIndex])) return true;
}
return false;
This loops over the list a single time, extracts the key elements from the array and composes a key for a HashMap. There are various ways to do this. But while it’s tempting to just concatenate these elements like rt[indices[0]] + "," + rt[indices[1]], which would work, using a List is preferable, as it avoids expensive string concatenation.
The code puts the value to check into the map which will return a previous value if this key has been encountered before. If so, the old and new values can be compared and the method can return immediately if they don’t match.
When you are using Java 8, you have to use Arrays.asList(rt[indices[0]], rt[indices[1]]) instead of List.of(rt[indices[0]], rt[indices[1]]).
This can be easily expanded to support variable lengths for indices, by changing
List<String> key = List.of(rt[indices[0]], rt[indices[1]]);
to
List<String> key = Arrays.stream(indices).mapToObj(i -> rt[i]).toList();
or, if you are using a Java version older than 16:
List<String> key
= Arrays.stream(indices).mapToObj(i -> rt[i]).collect(Collectors.toList());
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
}
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);
}
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);
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