Related
This question already has an answer here:
Remove a common word from each string value in an array
(1 answer)
Closed 6 years ago.
I have an array of Strings that contains: Extra Water, Juice, and Extra Milk, so I am wondering how would I get rid of the extras and use the only second word in the string so that the expected output is Water, Juice, and Milk.
If all you want to do is remove a specific substring then:
String[] array = {"Extra Water", "Juice", "Extra Milk"};
array = Arrays.stream(array).map(s-> s.replaceAll("Extra", "")).toArray();
This uses Java 8 streams but you could do it just as simply with iteration.
Use String.split(' ') to split the string by a space, then check the result to see if the string length == 2. If so, then take the second element of the array, otherwise the first.
for( int i = 0; i < array.length; i++ ) {
String[] parts = array[i].split(' ');
if( parts.length == 2 ) {
array[i] = parts[1];
}
}
EDIT: If you want to remove all duplicate words, you could do the following using two passes over the array:
// Pass 1 -- find all duplicate words
Set<String> wordSet = new HashSet<>();
Set<String> duplicateSet = new HashSet<>();
for (int i = 0; i < array.length; i++) {
String[] parts = array[i].split(" ");
for (String part : parts) {
if (!wordSet.contains(part)) {
// Haven't seen this word before
wordSet.add(part);
} else {
// This word is a duplicate word
if (!duplicateSet.contains(part)) {
duplicateSet.add(part);
}
}
}
}
// Pass 2 -- remove all words that are in the duplicate set
for (int i = 0; i < array.length; i++) {
String[] parts = array[i].split(" ");
String dedupedString = "";
for (String part : parts) {
if (!duplicateSet.contains(part)) {
dedupedString += part + " ";
}
}
array[i] = dedupedString;
}
Simply you need to iterate over each element of the array and replace the "Extra" in each element of the array and then trim the white spaces.
String[] array = {"Extra Water", "Juice", "Extra Milk"};
for (int i = 0; i < array.length; i++) {
array[i] = array[i].replace("Extra", "").trim();
}
for (String each : array) {
System.out.println(each);
}
This question already has answers here:
What is the simplest way to convert a Java string from all caps (words separated by underscores) to CamelCase (no word separators)?
(22 answers)
Closed 7 years ago.
convert string to camelCase
eg:
"user_id" to "userId"
"user_name" to "userName"
"country_province_city" to "countryProvinceCity"
how to do that in a easy way?
ps:"country_province_city" should be "countryProvinceCity" not "countryprovincecity"
I would use a loop and a StringBuilder. Something like
String[] arr = { "user_id", "user_name", "country_province_city" };
for (String str : arr) {
StringBuilder sb = new StringBuilder(str);
int pos;
while ((pos = sb.indexOf("_")) > -1) {
String ch = sb.substring(pos + 1, pos + 2);
sb.replace(pos, pos + 2, ch.toUpperCase());
}
System.out.printf("%s = %s%n", str, sb);
}
And I get the (requested)
user_id = userId
user_name = userName
country_province_city = countryProvinceCity
As Fast Snail mentions, simply use, for example, if String str = "user_id, user_name, user_id";, call str = str.replaceAll("userID", "user_id");, causing str to now have the value "userID, user_name, userID"
Alternatively, a more complete method would be as follows
public String toCamel(String str) {
String[] splits = str.split("_");
for (int i = 1; i < splits.length; i++) {
char first = Character.toUpperCase(splits.charAt(0));
if (splits[i].length() > 0)
splits[i] = first + splits[i].substring(1);
else
splits[i] = first + "";
}
String toRet = "";
for (String s : splits)
toRet += s;
return toRet;
}
This is a very simple one:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String result = "";
String input = scan.nextLine();
for (int i = 0; i < input.length(); i++) {
if (input.charAt(i) == '_') {
result += input.toUpperCase().charAt(i + 1);
i = i + 1;
} else {
result += input.toLowerCase().charAt(i);
}
}
System.out.println(result);
}
if you like to do it many times, I advice you to use a while loop to keep repeating the same code over and over again:
while (true) {
//the previous code
}
http://commons.apache.org/proper/commons-lang/javadocs/api-3.4/index.html
String str="country_province_city";
wordUtils.capitalize(str, '_');
str=str.replaceAll("_", "");
output: countryProvinceCity
For another point of view that the answers above you can also do it with split function and two loops, like this:
String[] strings = {"user_id","user_name","country_province_city"};
for (int i = 0; i < strings.length; i++)
{
String string = strings[i];
String totalString = "";
String[] divide = string.split("_");
for(int j = 0; j < divide.length; j++)
{
if(j != 0)
{
divide[j] = "" + divide[j].toUpperCase().charAt(0) + divide[j].substring(1,divide[j].length());
}
totalString = totalString + divide[j];
}
}
If you want to show this changed Strings by console you just have to add System.out.println after the second loop and inside the first one, like this:
for (int i = 0; i < strings.length; i++)
{
//The same code as the code that I put in the example above
for(int j = 0; j < divide.length; j++)
{
//The same code as the example above
}
System.out.println(totalString);
}
On the contrary, if your objective it's to store them into an array, you can do it like this:
String[] store;
for (int i = 0; i < strings.length; i++)
{
//The same code as the code that I put in the example above
store = new String[divide.length];
for(int j = 0; j < divide.length; j++)
{
//The same code as the example above
}
store[j] = totalString;
}
If you have any doubt about the code please let me know.
I expect it will help to you!
I have this String:
String string="NNP,PERSON,true,?,IN,O,false,pobj,NNP,ORGANIZATION,true,?,p";
How can I do to split it into an array every 4 commas?
I would like something like this:
String[] a=string.split("d{4}");
a[0]="NNP,PERSON,true,?";
a[1]="IN,O,false,pobj";
a[2]="NNP,ORGANIZATION,true,?";
a[3]="p";
Keep it simple. No need to use regex. Simply count the number of commas. when four commas are found then use String.substring() to find out the value.
Finally store the printed values in ArrayList<String>.
String string = "NNP,PERSON,true,?,IN,O,false,pobj,NNP,ORGANIZATION,true,?,p";
int count = 0;
int beginIndex = 0;
int endIndex = 0;
for (char ch : string.toCharArray()) {
if (ch == ',') {
count++;
}
if (count == 4) {
System.out.println(string.substring(beginIndex + 1, endIndex));
beginIndex = endIndex;
count = 0;
}
endIndex++;
}
if (beginIndex < endIndex) {
System.out.println(string.substring(beginIndex + 1, endIndex));
}
output:
NP,PERSON,true,?
IN,O,false,pobj
NNP,ORGANIZATION,true,?
p
If you really have to use split you can use something like
String[] array = string.split("(?<=\\G[^,]{1,100},[^,]{1,100},[^,]{1,100},[^,]{1,100}),");
Explanation if idea in my previous answer on similar but simpler topic
Demo:
String string = "NNP,PERSON,true,?,IN,O,false,pobj,NNP,ORGANIZATION,true,?,p";
String[] array = string.split("(?<=\\G[^,]{1,100},[^,]{1,100},[^,]{1,100},[^,]{1,100}),");
for (String s : array)
System.out.println(s);
output:
NNP,PERSON,true,?
IN,O,false,pobj
NNP,ORGANIZATION,true,?
p
But if there is any chance that you don't have to use split but you still want to use regex then I encourage you to use Pattern and Matcher classes to create simple regex which can find parts you are interested in, not complicated regex to find parts you want to get rid of. I mean something like
any xx,xxx,xxx,xxx part where x is not ,
any xx or xx,xx or xxx,xxx,xxx parts if they are placed at the end of string (to catch rest of data unmatched by regex from point 1.)
So
Pattern p = Pattern.compile("[^,]+(,[^,]+){3}|[^,]+(,[^,]+){0,2}$");
should do the trick.
Another solution and probably the fastest (and quite easy to write) would be creating your own parser which will iterate over all characters from your string, store them in some buffer, calculate how many , already occurred and if number is multiplication of 4 clear buffer and write its contend to array (or better dynamic collection like list). Such parser can look like
public static List<String> parse(String s){
List<String> tokens = new ArrayList<>();
StringBuilder sb = new StringBuilder();
int commaCounter = 0;
for (char ch: s.toCharArray()){
if (ch==',' && ++commaCounter == 4){
tokens.add(sb.toString());
sb.delete(0, sb.length());
commaCounter = 0;
}else{
sb.append(ch);
}
}
if (sb.length()>0)
tokens.add(sb.toString());
return tokens;
}
You can later convert List to array if you need but I would stay with List.
StringTokenizer tizer = new StringTokenizer (string,",");
int count = tizer.countTokens ()/4;
int overFlowCount = tizer.countTokens % 4;
String [] a;
if(overflowCount > 0)
a = new String[count +1];
else
a = new String[count];
int x = 0;
for (; x <count; x++){
a[x]= tizer.nextToken() + "," + tizer.nextToken() + "," + tizer.nextToken() + "," + tizer.nextToken();
}
if(overflowCount > 0)
while(tizer.hasMoreTokens()){
a[x+1] = a[x+1] + tizer.nextToken() + ",";
}
Edited,
Try this:
String str = "NNP,PERSON,true,?,IN,O,false,pobj,NNP,ORGANIZATION,true,?,p";
String[] arr = str.split(",");
ArrayList<String> result = new ArrayList<String>();
String s = arr[0] + ",";
int len = arr.length - (arr.length /4) * 4;
int i;
for (i = 1; i <= arr.length-len; i++) {
if (i%4 == 0) {
result.add(s.substring(0, s.length()-1));
s = arr[i] + ",";
}
else
s += arr[i] + ",";
}
s = "";
while (i <= arr.length-1) {
s += arr[i] + ",";
i++;
}
s += arr[arr.length-1];
result.add(s);
output:
NP,PERSON,true,?
IN,O,false,pobj
NNP,ORGANIZATION,true,?
p
This question already has answers here:
How to convert an int array to String with toString method in Java [duplicate]
(8 answers)
Closed 9 years ago.
I am trying to take an arbitrary-length String[] and print it out to a String, preferably with field separators. Right now I have:
String[] start = {"first", "second", "third"}; //[] to convert
String cC = "";
String finish = ""; // Final String
String cC1 = "";
{
for (int i = 0; i < puts.length; i++) {
cC = puts[i] + ", ";
cC1 = (finish + cC);
finish = cC1;
}
}
But for some reason it is only returning the "second" value. How can I make it properly concatenate the values?
Also, could I simplify the code by using finish += cC? Thanks.
String[] start = {"first", "second", "third"};
String addedTogether = Arrays.toString(start);
System.out.println(addedTogether);
//prints [first, second, third]
If You want to append to a string you should use +=
e.g.
String[] start = {"first", "second", "third"};
String cc = "";
String separator = ",";
for (int i = 0; i < start.length; i++) {
cc += start[i];
//Not Add , if it is the last element.
if(i!=start.length-1){
cc+=separator;
}
}
etc.
with your way you are setting the last value to finish.
String[] start = {"first", "second", "third"}; //[] to convert
String finish = ""; // Final String
{
for (int i = 0; i < starts.length; i++) {
finish = finish + start[i] + ", ";
}
}
(If you wanted to do all this manually for some reason...)
Check out -- Java equivalents of C# String.Format() and String.Join()
That provides a string.join method, as well as some reading on useful string utility methods.
It is a very bad idea to concatenate Strings using += operator. It is always better to construct StringBuilder object and append all the values to it. And lastly call toString() on the StringBuilder object.
Take a look at this link to understand the performance hit associated with using + operator for string concatenation.
http://blog.eyallupu.com/2010/09/under-hood-of-java-strings.html
How Java do the string concatenation using "+"?
I run into this case a lot of times when doing simple text processing and print statements where I am looping over a collection and I want to special case the last element (for example every normal element will be comma separated except for the last case).
Is there some best practice idiom or elegant form that doesn't require duplicating code or shoving in an if, else in the loop.
For example I have a list of strings that I want to print in a comma separated list. (the do while solution already assumes the list has 2 or more elements otherwise it'd be just as bad as the more correct for loop with conditional).
e.g. List = ("dog", "cat", "bat")
I want to print "[dog, cat, bat]"
I present 2 methods the
For loop with conditional
public static String forLoopConditional(String[] items) {
String itemOutput = "[";
for (int i = 0; i < items.length; i++) {
// Check if we're not at the last element
if (i < (items.length - 1)) {
itemOutput += items[i] + ", ";
} else {
// last element
itemOutput += items[i];
}
}
itemOutput += "]";
return itemOutput;
}
do while loop priming the loop
public static String doWhileLoopPrime(String[] items) {
String itemOutput = "[";
int i = 0;
itemOutput += items[i++];
if (i < (items.length)) {
do {
itemOutput += ", " + items[i++];
} while (i < items.length);
}
itemOutput += "]";
return itemOutput;
}
Tester class:
public static void main(String[] args) {
String[] items = { "dog", "cat", "bat" };
System.out.println(forLoopConditional(items));
System.out.println(doWhileLoopPrime(items));
}
In the Java AbstractCollection class it has the following implementation (a little verbose because it contains all edge case error checking, but not bad).
public String toString() {
Iterator<E> i = iterator();
if (! i.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = i.next();
sb.append(e == this ? "(this Collection)" : e);
if (! i.hasNext())
return sb.append(']').toString();
sb.append(", ");
}
}
I usually write it like this:
static String commaSeparated(String[] items) {
StringBuilder sb = new StringBuilder();
String sep = "";
for (String item: items) {
sb.append(sep);
sb.append(item);
sep = ",";
}
return sb.toString();
}
There are a lot of for loops in these answers, but I find that an Iterator and while loop reads much more easily. E.g.:
Iterator<String> itemIterator = Arrays.asList(items).iterator();
if (itemIterator.hasNext()) {
// special-case first item. in this case, no comma
while (itemIterator.hasNext()) {
// process the rest
}
}
This is the approach taken by Joiner in Google collections and I find it very readable.
string value = "[" + StringUtils.join( items, ',' ) + "]";
My usual take is to test if the index variable is zero, e.g.:
var result = "[ ";
for (var i = 0; i < list.length; ++i) {
if (i != 0) result += ", ";
result += list[i];
}
result += " ]";
But of course, that's only if we talk about languages that don't have some Array.join(", ") method. ;-)
I think it is easier to think of the first element as the special case because it is much easier to know if an iteration is the first rather than the last. It does not take any complex or expensive logic to know if something is being done for the first time.
public static String prettyPrint(String[] items) {
String itemOutput = "[";
boolean first = true;
for (int i = 0; i < items.length; i++) {
if (!first) {
itemOutput += ", ";
}
itemOutput += items[i];
first = false;
}
itemOutput += "]";
return itemOutput;
}
I'd go with your second example, ie. handle the special case outside of the loop, just write it a bit more straightforward:
String itemOutput = "[";
if (items.length > 0) {
itemOutput += items[0];
for (int i = 1; i < items.length; i++) {
itemOutput += ", " + items[i];
}
}
itemOutput += "]";
Java 8 solution, in case someone is looking for it:
String res = Arrays.stream(items).reduce((t, u) -> t + "," + u).get();
I like to use a flag for the first item.
ArrayList<String> list = new ArrayList()<String>{{
add("dog");
add("cat");
add("bat");
}};
String output = "[";
boolean first = true;
for(String word: list){
if(!first) output += ", ";
output+= word;
first = false;
}
output += "]";
Since your case is simply processing text, you don't need the conditional inside the loop. A C example:
char* items[] = {"dog", "cat", "bat"};
char* output[STRING_LENGTH] = {0};
char* pStr = &output[1];
int i;
output[0] = '[';
for (i=0; i < (sizeof(items) / sizeof(char*)); ++i) {
sprintf(pStr,"%s,",items[i]);
pStr = &output[0] + strlen(output);
}
output[strlen(output)-1] = ']';
Instead of adding a conditional to avoid generating the trailing comma, go ahead and generate it (to keep your loop simple and conditional-free) and simply overwrite it at the end. Many times, I find it clearer to generate the special case just like any other loop iteration and then manually replace it at the end (although if the "replace it" code is more than a couple of lines, this method can actually become harder to read).
...
String[] items = { "dog", "cat", "bat" };
String res = "[";
for (String s : items) {
res += (res.length == 1 ? "" : ", ") + s;
}
res += "]";
or so is quite readable. You can put the conditional in a separate if clause, of course. What it makes idiomatic (I think so, at least) is that it uses a foreach loop and does not use a complicated loop header.
Also, no logic is duplicated (i.e. there is only one place where an item from items is actually appended to the output string - in a real world application this might be a more complicated and lengthy formatting operation, so I wouldn't want to repeat the code).
In this case, you are essentially concatenating a list of strings using some separator string. You can maybe write something yourself which does this. Then you will get something like:
String[] items = { "dog", "cat", "bat" };
String result = "[" + joinListOfStrings(items, ", ") + "]"
with
public static String joinListOfStrings(String[] items, String sep) {
StringBuffer result;
for (int i=0; i<items.length; i++) {
result.append(items[i]);
if (i < items.length-1) buffer.append(sep);
}
return result.toString();
}
If you have a Collection instead of a String[] you can also use iterators and the hasNext() method to check if this is the last or not.
If you are building a string dynamically like that, you shouldn't be using the += operator.
The StringBuilder class works much better for repeated dynamic string concatenation.
public String commaSeparate(String[] items, String delim){
StringBuilder bob = new StringBuilder();
for(int i=0;i<items.length;i++){
bob.append(items[i]);
if(i+1<items.length){
bob.append(delim);
}
}
return bob.toString();
}
Then call is like this
String[] items = {"one","two","three"};
StringBuilder bob = new StringBuilder();
bob.append("[");
bob.append(commaSeperate(items,","));
bob.append("]");
System.out.print(bob.toString());
Generally, my favourite is the multi-level exit. Change
for ( s1; exit-condition; s2 ) {
doForAll();
if ( !modified-exit-condition )
doForAllButLast();
}
to
for ( s1;; s2 ) {
doForAll();
if ( modified-exit-condition ) break;
doForAllButLast();
}
It eliminates any duplicate code or redundant checks.
Your example:
for (int i = 0;; i++) {
itemOutput.append(items[i]);
if ( i == items.length - 1) break;
itemOutput.append(", ");
}
It works for some things better than others. I'm not a huge fan of this for this specific example.
Of course, it gets really tricky for scenarios where the exit condition depends on what happens in doForAll() and not just s2. Using an Iterator is such a case.
Here's a paper from the prof that shamelessly promoted it to his students :-). Read section 5 for exactly what you're talking about.
I think there are two answers to this question: the best idiom for this problem in any language, and the best idiom for this problem in java. I also think the intent of this problem wasn't the tasks of joining strings together, but the pattern in general, so it doesn't really help to show library functions that can do that.
Firstly though the actions of surrounding a string with [] and creating a string separated by commas are two separate actions, and ideally would be two separate functions.
For any language, I think the combination of recursion and pattern matching works best. For example, in haskell I would do this:
join [] = ""
join [x] = x
join (x:xs) = concat [x, ",", join xs]
surround before after str = concat [before, str, after]
yourFunc = surround "[" "]" . join
-- example usage: yourFunc ["dog", "cat"] will output "[dog,cat]"
The benefit of writing it like this is it clearly enumerates the different situations that the function will face, and how it will handle it.
Another very nice way to do this is with an accumulator type function. Eg:
join [] = ""
join strings = foldr1 (\a b -> concat [a, ",", b]) strings
This can be done in other languages as well, eg c#:
public static string Join(List<string> strings)
{
if (!strings.Any()) return string.Empty;
return strings.Aggregate((acc, val) => acc + "," + val);
}
Not very efficient in this situation, but can be useful in other cases (or efficiency may not matter).
Unfortunately, java can't use either of those methods. So in this case I think the best way is to have checks at the top of the function for the exception cases (0 or 1 elements), and then use a for loop to handle the case with more than 1 element:
public static String join(String[] items) {
if (items.length == 0) return "";
if (items.length == 1) return items[0];
StringBuilder result = new StringBuilder();
for(int i = 0; i < items.length - 1; i++) {
result.append(items[i]);
result.append(",");
}
result.append(items[items.length - 1]);
return result.toString();
}
This function clearly shows what happens in the two edge cases (0 or 1 elements). It then uses a loop for all but the last elements, and finally adds the last element on without a comma. The inverse way of handling the non-comma element at the start is also easy to do.
Note that the if (items.length == 1) return items[0]; line isn't actually necessary, however I think it makes what the function does more easier to determine at a glance.
(Note that if anyone wants more explanation on the haskell/c# functions ask and I'll add it in)
It can be achieved using Java 8 lambda and Collectors.joining() as -
List<String> items = Arrays.asList("dog", "cat", "bat");
String result = items.stream().collect(Collectors.joining(", ", "[", "]"));
System.out.println(result);
I usually write a for loop like this:
public static String forLoopConditional(String[] items) {
StringBuilder builder = new StringBuilder();
builder.append("[");
for (int i = 0; i < items.length - 1; i++) {
builder.append(items[i] + ", ");
}
if (items.length > 0) {
builder.append(items[items.length - 1]);
}
builder.append("]");
return builder.toString();
}
If you are just looking for a comma seperated list of like this: "[The, Cat, in, the, Hat]", don't even waste time writing your own method. Just use List.toString:
List<String> strings = Arrays.asList("The", "Cat", "in", "the", "Hat);
System.out.println(strings.toString());
Provided the generic type of the List has a toString with the value you want to display, just call List.toString:
public class Dog {
private String name;
public Dog(String name){
this.name = name;
}
public String toString(){
return name;
}
}
Then you can do:
List<Dog> dogs = Arrays.asList(new Dog("Frank"), new Dog("Hal"));
System.out.println(dogs);
And you'll get:
[Frank, Hal]
A third alternative is the following
StringBuilder output = new StringBuilder();
for (int i = 0; i < items.length - 1; i++) {
output.append(items[i]);
output.append(",");
}
if (items.length > 0) output.append(items[items.length - 1]);
But the best is to use a join()-like method. For Java there's a String.join in third party libraries, that way your code becomes:
StringUtils.join(items,',');
FWIW, the join() method (line 3232 onwards) in Apache Commons does use an if within a loop though:
public static String join(Object[] array, char separator, int startIndex, int endIndex) {
if (array == null) {
return null;
}
int bufSize = (endIndex - startIndex);
if (bufSize <= 0) {
return EMPTY;
}
bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length()) + 1);
StringBuilder buf = new StringBuilder(bufSize);
for (int i = startIndex; i < endIndex; i++) {
if (i > startIndex) {
buf.append(separator);
}
if (array[i] != null) {
buf.append(array[i]);
}
}
return buf.toString();
}