Remove last set of value from a comma separated string in java - 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

Related

How to explode a string on a hyphen in Java?

I have a task which involves me creating a program that reads text from a text file, and from that produces a word count, and lists the occurrence of each word used in the file. I managed to remove punctuation from the word count but I'm really stumped on this:
I want java to see this string "hello-funny-world" as 3 separate strings and store them in my array list, this is what I have so far , with this section of code I having issues , I just get "hello funny world" seen as one string:
while (reader.hasNext()){
String nextword2 = reader.next();
String nextWord3 = nextword2.replaceAll("[^a-zA-Z0-9'-]", "");
String nextWord = nextWord3.replace("-", " ");
int apcount = 0;
for (int i = 0; i < nextWord.length(); i++){
if (nextWord.charAt(i)== 39){
apcount++;
}
}
int i = nextWord.length() - apcount;
if (wordlist.contains(nextWord)){
int index = wordlist.indexOf(nextWord);
count.set(index, count.get(index) + 1);
}
else{
wordlist.add(nextWord);
count.add(1);
if (i / 2 * 2 == i){
wordlisteven.add(nextWord);
}
else{
wordlistodd.add(nextWord);
}
}
This can work for you ....
List<String> items = Arrays.asList("hello-funny-world".split("-"));
By considering that you are using the separator as '-'
I would suggest you to use simple split() of java
String name="this-is-string";
String arr[]=name.split("-");
System.out.println("Here " +arr.length);
Also you will be able to iterate through this array using for() loop
Hope this helps.

Mask part of the String data which is of different lengths using Java

I am in need to mask PII data for my application. The PII data will be of String format and of variable lengths, as it may include name, address, mail id's etc.
So i need to mask these data before logging them, it should not be a full mask instead, if the length of string is less than or equal to 8 characters then mask the first half with "XXX etc.."
If the length is more than 8 then mask the first and last portion of the string such that only the mid 5 characters are visible.
I know we can do this using java sub-stringa nd iterating over the string, but want to know if there is any other simple solution to address this.
Thanks in advance
If you are using Apache Commons, you can do like
String maskChar = "*";
//number of characters to be masked
String maskString = StringUtils.repeat( maskChar, 4);
//string to be masked
String str = "FirstName";
//this will mask first 4 characters of the string
System.out.println( StringUtils.overlay(str, maskString, 0, 4) );
You can check the string length before generating maskString using if else statement.
You can use this function; change the logic of half's as per your needs:
public static String maskedVariableString(String original)
{
String maskedString = null;
if(original.length()<9)
{
int half = original.length()/2;
StringBuilder sb =new StringBuilder("");
for(int i=0;i<(original.length()-half);i++)
{
sb.append("X");
}
maskedString = original.replaceAll("\\b.*(\\d{"+half+"})", sb.toString()+"$1");
}
else
{
int maskLength = original.length()-5;
int firstMaskLength = maskLength/2;
int secondMaskLength = maskLength-firstMaskLength;
StringBuilder sb =new StringBuilder("");
for(int i=0;i<firstMaskLength;i++)
{
sb.append("X");
}
String firstMask = sb.toString();
StringBuilder sb1 =new StringBuilder("");
for(int i=0;i<secondMaskLength;i++)
{
sb1.append("X");
}
String secondMask = sb1.toString();
maskedString = original.replaceAll("\\b(\\d{"+firstMaskLength+"})(\\d{5})(\\d{"+secondMaskLength+"})", firstMask+"$2"+secondMask);
}
return maskedString;
}
Explanation:
() groups the regular expression and we can use $ to access this group($1, $2,$3).
The \b boundary helps check that we are the start of the digits (there are other ways to do this, but here this will do).
(\d{+half+}) captures (half) no of digits to Group 1. The same happens in the else part also.

simple mathematical expression parsing

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
}

Ignoring upper/lowercase strings

My goal is to change any form of the word "java" in a sentence to "JAVA".I've got everything done but my code won't read in mixed cases for example:JaVa, JAva,etc. I know I am suppose to use toUpperCase and toLowerCase or equalsIgnoreCase but I am not sure how to use it properly. I am not allowed to use replace or replace all, teacher wants substring method.
Scanner input=new Scanner(System.in);
System.out.println("Enter a sentence with words including java");
String sentence=input.nextLine();
String find="java";
String replace="JAVA";
String result="";
int n;
do{
n=sentence.indexOf(find);
if(n!=-1){
result =sentence.substring(0,n);
result=result +replace;
result = result + sentence.substring(n+find.length());
sentence=result;
}
}while(n!=-1);
System.out.println(sentence);
}
}
You can't do that using String.indexOf because it is case sensitive.
The simple solution is to use a regex with a case insensitive pattern; e.g.
Pattern.compile(regex, Pattern.CASE_INSENSITIVE).matcher(str).replaceAll(repl);
That also has the benefit of avoiding the messy string-bashing you are currently using to do the replacement.
In your example, your input string is also valid as a regex ... because it doesn't include any regex meta-characters. If it did, then the simple workaround is to use Pattern.quote(str) which will treat the meta-characters as literal matches.
It is also worth nothing that String.replaceAll(...) is a "convenience method" for doing a regex replace on a string, though you can't use it for your example because it does case sensitive matching.
For the record, here is a partial solution that does the job by string-bashing. #ben - this is presented for you to read and understand ... not to copy. It is deliberately uncommented to encourage you to read it carefully.
// WARNING ... UNTESTED CODE
String input = ...
String target = ...
String replacement = ...
String inputLc = input.lowerCase();
String targetLc = target.lowerCase();
int pos = 0;
int pos2;
while ((pos2 = inputLc.indexOf(targetLc, pos)) != -1) {
if (pos2 - pos > 0) {
result += input.substring(pos, pos2);
}
result += replacement;
pos = pos2 + target.length();
}
if (pos < input.length()) {
result += input.substring(pos);
}
It probably be more efficient to use a StringBuilder instead of a String for result.
you are allowed to use toUpperCase() ? try this one
Scanner input=new Scanner(System.in);
System.out.println("Enter a sentence with words including java");
String sentence=input.nextLine();
String find="java";
String replace="JAVA";
String result="";
result = sentence.toLowerCase();
result = result.replace(find,replace);
System.out.println(result);
}
reply with the result :))
Update : Based on
I've got everything done but my code won't read in mixed cases for
example:JaVa, JAva,etc.
you can use your code
Scanner input=new Scanner(System.in);
System.out.println("Enter a sentence with words including java");
String sentence=input.nextLine();
String find="java";
String replace="JAVA";
String result="";
int n;
do{
//for you to ignore(converts the sentence to lowercase) either lower or upper case in your sentence then do the nxt process
sentence = sentence.toLowerCase();
n=sentence.indexOf(find);
if(n!=-1){
result =sentence.substring(0,n);
result=result +replace;
result = result + sentence.substring(n+find.length());
sentence=result;
}
}while(n!=-1);
System.out.println(sentence);
}
Update 2 : I put toLowerCase Convertion outside the loop.
public static void main(String[] args){
String sentence = "Hello my name is JAva im a jaVa Man with a jAvA java Ice cream";
String find="java";
String replace="JAVA";
String result="";
int n;
//for you to ignore(converts the sentence to lowercase) either lower or upper case in your sentence then do the nxt process
sentence = sentence.toLowerCase();
System.out.println(sentence);
do{
n=sentence.indexOf(find);
if(n!=-1){
result =sentence.substring(0,n);
result=result +replace;
result = result + sentence.substring(n+find.length());
sentence=result;
}
}while(n!=-1);
System.out.println(sentence);
}
RESULT
hello my name is java im a java man with a java java ice cream
hello my name is JAVA im a JAVA man with a JAVA JAVA ice cream
A quick solution would be to remove your do/while loop entirely and just use a case-insensitive regex with String.replaceAll(), like:
sentence = sentence.replaceAll("(?i)java", "JAVA");
System.out.println(sentence);
Or, more general and according to your variable namings:
sentence = sentence.replaceAll("(?i)" + find, replace);
System.out.println(sentence);
Sample Program
EDIT:
Based on your comments, if you need to use the substring method, here is one way.
First, since String.indexOf does case-sensitive comparisons, you can write your own case-insensitive method, let's call it indexOfIgnoreCase(). This method would look something like:
// Find the index of the first occurrence of the String find within the String str, starting from start index
// Return -1 if no match is found
int indexOfIgnoreCase(String str, String find, int start) {
for(int i = start; i < str.length(); i++) {
if(str.substring(i, i + find.length()).equalsIgnoreCase(find)) {
return i;
}
}
return -1;
}
Then, you can use this method in the following manner.
You find the index of the word you need, then you add the portion of the String before this word (up to the found index) to the result, then you add the replaced version of the word you found, then you add the rest of the String after the found word.
Finally, you update the starting search index by the length of the found word.
String find = "java";
String replace = "JAVA";
int index = 0;
while(index + find.length() <= sentence.length()) {
index = indexOfIgnoreCase(sentence, find, index); // use the custom indexOf method here
if(index == -1) {
break;
}
sentence = sentence.substring(0, index) + // copy the string up to the found word
replace + // replace the found word
sentence.substring(index + find.length()); // copy the remaining part of the string
index += find.length();
}
System.out.println(sentence);
Sample Program
You could use a StringBuilder to make this more efficient since the + operator creates a new String on each concatenation. Read more here
Furthermore, you could combine the logic in the indexOfIgnoreCase and the rest of the code in a single method like:
String find = "java";
String replace = "JAVA";
StringBuilder sb = new StringBuilder();
int i = 0;
while(i + find.length() <= sentence.length()) {
// if found a match, add the replacement and update the index accordingly
if(sentence.substring(i, i + find.length()).equalsIgnoreCase(find)) {
sb.append(replace);
i += find.length();
}
// otherwise add the current character and update the index accordingly
else {
sb.append(sentence.charAt(i));
i++;
}
}
sb.append(sentence.substring(i)); // append the rest of the string
sentence = sb.toString();
System.out.println(sentence);

Parsing comma-separated values enclosed with quotes

I'm trying to parse comma separated values that are enclosed in quotes using only standard Java libraries (I know this must be possible)
As an example file.txt contains a new line for each row of
"Foo","Bar","04042013","04102013","Stuff"
"Foo2","Bar2","04042013","04102013","Stuff2"
However when I parse the file with the code I've written so far:
import java.io.*;
import java.util.Arrays;
public class ReadCSV{
public static void main(String[] arg) throws Exception {
BufferedReader myFile = new BufferedReader(new FileReader("file.txt"));
String myRow = myFile.readLine();
while (myRow != null){
//split by comma separated quote enclosed values
//BUG - first and last values get an extra quote
String[] myArray = myRow.split("\",\""); //the problem
for (String item:myArray) { System.out.print(item + "\t"); }
System.out.println();
myRow = myFile.readLine();
}
myFile.close();
}
}
However the output is
"Foo Bar 04042013 04102013 Stuff"
"Foo2 Bar2 04042013 04102013 Stuff2"
Instead of
Foo Bar 04042013 04102013 Stuff
Foo2 Bar2 04042013 04102013 Stuff2
I know I went wrong on the Split but I'm not sure how to fix it.
Before doing split, just remove first double quote and last double quote in myRow variable using below line.
myRow = myRow.substring(1, myRow.length() - 1);
(UPDATE) Also check if myRow is not empty. Otherwise above code will cause exception. For example below code checks if myRow is not empty and then only removes double quotes from the string.
if (!myRow.isEmpty()) {
myRow = myRow.substring(1, myRow.length() - 1);
}
i think you will probably have to go for a stateful approach, basically like the code below (another state would be necessary if you want to allow escaping of quotes within a value):
import java.util.ArrayList;
import java.util.List;
public class CSV {
public static void main(String[] args) {
String s = "\"hello, i am\",\"a string\"";
String x = s;
List<String> l = new ArrayList<String>();
int state = 0;
while(x.length()>0) {
if(state == 0) {
if(x.indexOf("\"")>-1) {
x = x.substring(x.indexOf("\"")+1).trim();
state = 1;
} else {
break;
}
} else if(state == 1) {
if(x.indexOf("\"")>-1) {
String found = x.substring(0,x.indexOf("\""));
System.err.println("found: "+found);
l.add(found);
x = x.substring(x.indexOf("\"")+1).trim();
state = 0;
} else {
throw new RuntimeException("bad format");
}
} else if(state == 2) {
if(x.indexOf(",")>-1) {
x = x.substring(x.indexOf(",")+1).trim();
state = 0;
} else {
break;
}
}
}
for(String f : l) {
System.err.println(f);
}
}
}
Instead, you can use replaceAll, which, for me, looks more suitable for this task:
myRow = myRow.replaceAll("\"", "").replaceAll(","," ");
This will replace all the " with nothing (Will remove them), then it'll replace all , with space (You can increase the number of spaces of course).
The problem in above code snippet is that you are splitting the String based on ",".
on your Line start "foo"," and end ","stuff" the starting and ending quotes does not match with "," so there are not splitted.
so this definitely not a bug in java. in your case you need to handle that part yourself.
You have multiple options to do it. some of them can be like below.
1. If you are sure there will be always a starting " and ending " you can remove them from String before hand before splitting.
2. If the starting " and " are optional, you can first check it with startsWith endsWith and then remove if exists before splitting.
You can simply get the String delimitered by the comma and then delete the first and last '"'.
=)
hope thats helpfull
dont have much time :D
String s = "\"Foo\",\"Bar\",\"04042013\",\"04102013\",\"Stuff\"";
String[] bufferArray = new String[10];
String bufferString;
int i = 0;
System.out.println(s);
Scanner scanner = new Scanner(s);
scanner.useDelimiter(",");
while(scanner.hasNext()) {
bufferString = scanner.next();
bufferArray[i] = bufferString.subSequence(1, bufferString.length() - 1).toString();
i++;
}
System.out.println(bufferArray[0]);
System.out.println(bufferArray[1]);
System.out.println(bufferArray[2]);
This solution is less elegant than a String.split() oneliner. The advantage is that we avoid fragile string manipulation, ie. the use of String.substring(). The string must end with ," however.
This version handles spaces between delimiters. Delimiter characters within quotes are ignored as expected, as are escaped quotes (for example \").
String s = "\"F\\\",\\\"oo\" , \"B,ar\",\"04042013\",\"04102013\",\"St,u\\\"ff\"";
Pattern p = Pattern.compile("(.*?)\"\\s*,\\s*\"");
Matcher m = p.matcher(s + ",\""); // String must end with ,"
while (m.find()) {
String result = m.group(1);
System.out.println(result);
}

Categories