I am unable to delete all my upper case characters in my string. Any insight is appreciated.
if I input MANDY as str, I get output as AD. I am not sure why it is has this behavior.
StringBuilder outString = new StringBuilder(str);
for(int i = 0; i<outString.length(); i++){
if(Character.isUpperCase(outString.charAt(i))){
outString.deleteCharAt(i);
}
}
return outString.toString();
Thanks
By deleting the characters you change the indexes, so every uppercase character after another is not deleted.
A simple "trick" is to iterate the buffer the other way around (starting at the end). That way you only affect the indexes of already processed characters
for(int i = outString.length()-1; i>=0; i--){
if(Character.isUpperCase(outString.charAt(i))){
outString.deleteCharAt(i);
}
}
You can do this using regex:
String s = "MANDYs";
s = s.replaceAll("[A-Z]", "");
System.out.println(s);
You are increasing index while you are deleting items from the String you are iterating. I would call it a case of Concurrent Modification, though StringBuilder doesn't give any exception.
Better is to do this:
int i = 0;
while (i < outString.length()) {
if (Character.isUpperCase(outString.charAt(i))) {
outString.deleteCharAt(i);
} else {
i++;
}
}
Related
I have a piece of code and I'm a bit confused how to deal with my issue so, please review method below. I was trying to search for a solution but unfortunately none of them fit my needs so I am looking for an advice here. The method is taking a String and removing duplicated characters so for example - input: ABBCDEF should return ABCDEF, but when entering i+1 in the last iteration I got IndexOutOfBound Exception, so I can iterate until string.length-1 but then I loose the last element, what is the SMARTEST solution in your opinion, thanks.
public String removeDuplicates(String source){
if(source.length() < 2){
return source;
}
StringBuilder noDuplicates = new StringBuilder();
char[] string = source.toCharArray();
for(int i = 0; i < string.length-1; i++){
if(string[i] != string[i+1]){
noDuplicates.append(string[i]);
}
}
return noDuplicates.toString();
}
You could do this like so: append the first character in source, and then only append subsequent characters if they are not equal to the previously-appended character.
if (source.isEmpty()) {
return source; // Or "", it doesn't really matter.
}
StringBuilder sb = new StringBuilder();
sb.append(source.charAt(0));
for (int i = 1; i < source.length(); ++i) {
char c = source.charAt(i);
if (c != sb.charAt(sb.length() - 1)) {
sb.append(c);
}
}
return sb.toString();
But if you wanted to do this more concisely, you could do it with regex:
return source.replaceAll("(.)\\1+", "$1");
You could simply append the last character after the loop:
public String removeDuplicates(String source){
...
noDuplicates.append(string[string.length - 1]);
return noDuplicates.toString();
}
You have a simple logic error:
You make your string to a char array.
That is fine, but the length property of any array will show you the
human way of counting if someting is in it.
If there is 1 element the length will be 1
2 -> 2
3 -> 3
etc.
You get the idea.
So when you go string[i + 1] you go one character to far.
You could just change the abort condition to
i < = string.length - 2
Or you could write a string iterator, to be able to access the next element, but
that seems like overkill for this example
This is just what LinkedHashSet was made for! Under the hood it's a HashSet with an iterator to keep track of insertion order, so you can remove duplicates by adding to the set, then reconstruct the string with guaranteed ordering.
public static String removeDuplicates(String source) {
Set<String> dupeSet = new LinkedHashSet<>();
for (Character v : source.toCharArray()) {
dupeSet.add(v.toString());
}
return String.join("", dupeSet);
}
If you wish to remove all repeating characters regardless of their position in the given String you might want to consider using the chars() method which provides a IntStream of the chars and that has the distinct() method to filter out repeating values. You can then put them back together with a StringBuilder like so:
public class RemoveDuplicatesTest {
public static void main(String[] args) {
String value = "ABBCDEFE";
System.out.println("No Duplicates: " + removeDuplicates(value));
}
public static String removeDuplicates(String value) {
StringBuilder result = new StringBuilder();
value.chars().distinct().forEach(c -> result.append((char) c));
return result.toString();
}
}
I am attempting to add a comma separator to the String representation of a Java ArrayList but nothing seems to work, I am obviously missing something simple.
Sadly old Java 6 (running in a JSP):
ArrayList zones= new ArrayList();
zones.add(pageContext.getAttribute("zone"));
for(int i=0; i<zones.size(); i++)
out.println(zones.get(i));
// output is CellA116 CellA116 CellA116 Reception Reception CellA11
StringBuffer stringBuffer = new StringBuffer();
for(int i=0; i<zones.size(); i++)
{
stringBuffer.append(zones.get(i));
stringBuffer.append(",");
}
out.println(stringBuffer.toString());
// output is CellA116,CellA116,CellA116,Reception,Reception,CellA11, (commas)
%>
</tr>
</c:forEach>
syntax wont work here (outside of loop)
out.println(stringBuffer.substring(0, stringBuffer.length() - 1));
I need to remove the final comma (as I eventually want to use the array in chart.js), appreciate any thoughts.
Generally speaking, relying on a toString() method to do this is an easy way to inadvertently introduce bugs later on. If you change what concrete class is providing the collection (maybe to a Set instead of a List for example), your assumption that it starts and ends with square brackets might be untrue, and your output might change without you realising it.
I'd suggest that a more appropriate solution would be to iterate over the collection of Strings and add them to a StringBuilder.
So, it might look something like:
StringBuilder stringBuilder = new StringBuilder();
for(int i=0; i<strList.size(); i++)
{
stringBuilder.append(strList.get(i));
stringBuilder.append(",");
}
// Remove the last character from the StringBuilder to avoid a trailing comma.
String commaSeparatedList = stringBuilder.substring(0, stringBuilder.length() - 1);
out.println(commaSeparatedList);
You can utilize a StringBuilder and a classic for loop to output a csv line from List<String>.
Have a look at this:
public static void main(String args[]) {
List<String> zones = new ArrayList<String>();
zones.add("CellA116");
zones.add("CellA116");
zones.add("CellA116");
zones.add("Reception");
zones.add("Reception");
zones.add("CellA11");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < zones.size(); i++) {
if (i < zones.size() - 1) {
sb.append(zones.get(i)).append(";");
} else {
sb.append(zones.get(i));
}
}
System.out.println(sb.toString());
}
The output will look like this:
CellA116;CellA116;CellA116;Reception;Reception;CellA11
If you want to have a method with a flexible separator char, then use something like this:
public static String toSeparatedString(List<String> values, char separator) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < values.size(); i++) {
if (i < values.size() - 1) {
sb.append(values.get(i)).append(separator);
} else {
sb.append(values.get(i));
}
}
return sb.toString();
}
I dont see the need for another for loop to replace the [] and , zones.toString().replaceAll("[\[\]\s]", "") suggested by Lino works well.
I'm searching for a way to delete each 4th occurrence of a character (a-zA-Z) in a row.
For example, if I have the following string:
helloooo I am veeeeeeeeery busy right nowww because I am working veeeeeery hard
I want delete all 4th, 5th, 6th, ... characters in a row. But, in the word hard, a 4th r occurs, which I do NOT want to delete, because it is not the 4th r in a row / it is surrounded with other characters. The result should be:
hellooo I am veeery busy right nowww because I am working veeery hard
I have already searched for a way to do this, and I could have found a way to replace/delete the 4th occurrence of a character, but I could not find a way to replace/delete the 4th occurrence of a character in a row.
Thanks in advance.
The function may be written like this:
public static String transform(String input) {
if (input.isEmpty()) {
return input;
} else {
final StringBuilder sb = new StringBuilder();
char lastChar = '\0';
int duplicates = 0;
for (int i = 0; i < input.length(); i++) {
final char curChar = input.charAt(i);
if (curChar == lastChar) {
duplicates++;
if (duplicates < 3) {
sb.append(curChar);
}
} else {
sb.append(curChar);
lastChar = curChar;
duplicates = 0;
}
}
return sb.toString();
}
}
I think it's faster than regex.
In Java you can use this replacement based on back-references:
str = str.replaceAll("(([a-zA-Z])\\2\\2)\\2+", "$1");
Code Demo
RegEx Demo
The regex you want is ((.)\2{2})\2*. Not quite sure what that is in Java-ese, but what it does is match any single character and then 2 additional instances of that character, followed by any number of additional instances. Then replace it with the contents of the first capture group (\1) and you're good to go.
I have a String array which contains both integer and non-integer elements, and I need to remove all the non-integer elements of that array.
Now I am only able to remove the non-integer content in a single string, but I need to remove the entire non-integer elements in an array.
My snippet as follows
String str = "a12.334tyz.78x";
str = str.replaceAll("[^\\d.]", "");
Can anyone help me to achieve it?
You can achieve it by below code
Pattern p = Pattern.compile("\\d*");
String [] array=new String[]{"23","33.23","4d","ff"};
List<String> lst=new ArrayList<String>();
for (int i=0; i<array.length; i++) {
if(p.matcher(array[i]).matches()){
lst.add(array[i]);
}
}
System.out.println(""+lst);
Your original code is this:
String str = "a12.334tyz.78x";
str = str.replaceAll("[^\\d.]", "");
First, if you need to remove all non-integer character, you need to change your regex from "[^\d.]" to "[^\d]".
Yours will not remove dots character.
Then, you said:
Now I am only able to remove the non-integer content in a single
string, but I need to remove the entire non-integer elements in an
array.
Maybe I'm not getting this right, but isn't just a matter of looping while doing the same thing ? You didn't show us any code with loops, but perhaps your true problem is reassigning the modified value to the array ?
try this:
for(int i=0;i<strArray.length;i++){
strArray[i] = strArray[i].replaceAll("[^\\d]", "");
}
MAYBE you were doing something like this ? (this does not work):
for(String str: strArray){
str = str.replaceAll("[^\\d]", "");
}
That doesn't work because the modified string is not reassigned to the array, it is assigned to the new variable 'str'. So this code does not update the value pointed by the array.
replace all numbers - str = str.replaceAll("\\d", "");
replace all non-numbers - str = str.replaceAll("[^\\d]", "");
to do so in an array, iterate over the Array and do the replacment.
To remove all the non-integer values form a string you can try the following:
public boolean isInt(String s)
{
for(int i = 0; i < s.length(); i++)
{
try
{
Integer.parseInt(String.valueOf(s.charAt(i)));
}catch(NumberFormatException e)
{
return false;
}
}
return true;
}
Then you can iterate your array and remove the non-integer elements like this
for(int i = 0; i < arr.length; i++)
{
if(isInt(arr[i]))//remove the element
}
It would probably be easier to remove elements from a list than from an array. However, you can stream the elements of the array, remove invalid elements with flatMap, and then convert back to an array.
When using flatMap, each element in the input can produce zero, one, or many elements in the output, so we map the valid ones to singleton streams containing just that element, and the invalid ones to empty streams, thus removing them from the result.
String[] result = Arrays.stream(input)
.flatMap(a -> Pattern.matches("\\d+", a)?
Stream.of(a) : Stream.empty())
.toArray(String[]::new);
If your regex is working correctly, you already solved most of your problem. You only need to use your code in a for loop. You can try the code below:
public String[] removeNonIntegersFromArray(String[] array){
ArrayList<String> temp = new ArrayList<String>();
for (int i=0; i<array.length; i++) {
String str = array[i];
if(!str.matches(".*[^\\d]+.*")){
temp.add(str);
}
}
String[] result = new String[temp.size()];
result = (String[]) temp.toArray(new String[temp.size()]);
return result;
}
Edit: I refactored the code as it will delete whole array element which has non-integer.
Here is an idea,
Instead of replacing all non-int number, to find all integer and add them to a new string.
for(int i=0;i<str.length();i++)
{
if(Character.isDigit(str.charAt(i)))
new_str.append(str.charAt(i));
}
I need to convert a string vector in a simple string. I do not know how to proceed.
I tried various solutions such as
for(int i=1; i < easy.length; i++){
easyPuzzle = easy[i].toString();
}
System.out.println(" " + easyPuzzle);
but this solution prints only the ith element and not the entire string vector.
Use toString in Arrays class
Arrays.toString(easy);
You keep reassign a new value to easyPuzzle when you really want to concatenate:
easyPuzzle += easy[i].toString();
If easy.length is large, it might make sense to use a StringBuilder which is more efficient at concatenating than String:
StringBuilder builder = new StringBuilder();
for(int i=1; i < easy.length; i++){
builder.append(easy[i].toString());
}
easyPuzzle = builder.toString();
Also by starting your for loop at i=1 you exclude the first item. Not sure if it is on purpose or not. If not, start at i = 0.
Alternatively, to save the pain of writing the loop yourself, you can use #Manoj's answer which replaces your code by one line.
I recommend to you use StringBuilder with append(<data>) method and then convert it to String.
StringBuilder data = new StringBuilder();
for(int i = 1; i < easy.length; i++){
data.append(easy[i].toString());
}
easyPuzzle = data.toString();
String is immutable so work with it is much more consume. When you work with String, i recommend to you use StringBuilder, is more effective and faster.
Update: #Manoj answer is very usefull.