I am attempting to split a string into a list of strings delimited on the change of if a character can be casted numerically or not. To say it another way, I want to break my string up into distinct groups of numbers and letters. For added fun, I'm also trying to trim any leading 0's from each group of numbers. Consider the following example.
Say you're given "aoeu01234stnh0987" as your input. The output I want is ["aoeu", "1234", "stnh", "987"]
I made a working example below, but it is somewhat long and confusing. It seems like there must be a better, more concise way to achieve this.
private static List<String> fragmentString(String string) {
char[] charArr = string.toCharArray();
StringBuilder tempStr = new StringBuilder();
StringBuilder tempInt = new StringBuilder();
List<String> tempList = new ArrayList<>();
boolean wasPrevNum = false;
for (char c : charArr) {
boolean isNum = Character.isDigit(c);
if (isNum) {
tempInt.append(c);
if (!wasPrevNum) {
wasPrevNum = true;
tempList.add(tempStr.toString());
tempStr = new StringBuilder();
}
} else {
tempStr.append(c);
if(wasPrevNum) {
while (tempInt.charAt(0) == '0') tempInt.deleteCharAt(0);
tempList.add(tempInt.toString());
tempInt = new StringBuilder();
wasPrevNum = false;
}
}
}
if (tempInt.length() > 0) while (tempInt.charAt(0) == '0') tempInt.deleteCharAt(0);
tempList.add(wasPrevNum ? tempInt.toString() : tempStr.toString());
return tempList;
}
I saw this post about using the split() method, but that solution only works for their very specific case and doesn't apply here. The split() method was the first thing I played with to solve this, but I couldn't figure out a regex, and now I'm questioning if this is even possible using split().
A very simple solution can be using regex. The regex, \p{L}+|[0-9]+, which means sequence of letters or sequence of digits, can be used to find the substrings. Then, try to parse the found substring. If it is an integer, the leading zeros will be removed as a result of parsing and if the parsing fails, simply print the substring.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Main {
public static void main(String[] args) {
String str = "aoeu01234stnh0987";
Matcher matcher = Pattern.compile("\\p{L}+|[0-9]+").matcher(str);
while (matcher.find()) {
String substring = matcher.group();
try {
System.out.println(Integer.parseInt(substring));
} catch (NumberFormatException e) {
System.out.println(substring);
}
}
}
}
Output:
aoeu
1234
stnh
987
This example isn't much more concise than the code the OP posted. The best I can say is that I'm not using an exception as a part of my processing.
Here are the results from one test run.
aoeu01234stnh0987
[aoeu, 1234, stnh, 987]
Here's the complete runnable example code.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class StringSplitter {
public static void main(String[] args) {
StringSplitter ss = new StringSplitter();
String input = "aoeu01234stnh0987";
System.out.println(input);
List<String> output = ss.splitString(input);
String[] output2 = output.toArray(new String[output.size()]);
System.out.println(Arrays.toString(output2));
}
public List<String> splitString(String input) {
List<String> output = new ArrayList<>();
if (input == null || input.length() < 1) {
return output;
}
char c = input.charAt(0);
boolean isDigit = Character.isDigit(c);
StringBuilder builder = new StringBuilder();
builder.append(c);
for (int i = 1; i < input.length(); i++) {
c = input.charAt(i);
if (isDigit == Character.isDigit(c)) {
builder.append(c);
} else {
addToList(output, builder, isDigit);
builder.delete(0, builder.length());
builder.append(c);
isDigit = !isDigit;
}
}
addToList(output, builder, isDigit);
return output;
}
private void addToList(List<String> output,
StringBuilder builder, boolean isDigit) {
if (isDigit) {
output.add(Integer.toString(
Integer.valueOf(builder.toString())));
} else {
output.add(builder.toString());
}
}
}
You can add some delimiter characters to each group of symbols, and then split the string around these characters:
String str = "aoeu01234stnh0987";
String[] arr = str.replaceAll("\\d+|\\D+", "$0::::").split("::::", 0);
System.out.println(Arrays.toString(arr)); // [aoeu, 01234, stnh, 0987]
// trim leading zeros from numbers,
// i.e. parse the integer value
// and return it back to the string
IntStream.range(0, arr.length)
.filter(i -> arr[i].replaceAll("\\d+", "").length() == 0)
.forEach(i -> arr[i] = Integer.valueOf(arr[i]).toString());
System.out.println(Arrays.toString(arr)); // [aoeu, 1234, stnh, 987]
See also: How to split the string into string and integer in java?
I'm posting the code I ended up using in production, just in case it benefits anyone; I know there are already some great answers, and I used information from some answers here to come up with this.
private static List<List<String>> fragmentArr(String[] inputArr) {
List<List<String>> fragArr = new ArrayList<>();
Arrays.stream(inputArr).forEach(string -> {
List<String> listToAdd = new ArrayList<>();
Matcher matcher = Pattern.compile("[^0-9]+|[0-9]+").matcher(string);
while (matcher.find()) {
StringBuilder substring = new StringBuilder(matcher.group());
while (substring.charAt(0) == '0') substring.deleteCharAt(0);
listToAdd.add(substring.toString());
}
fragArr.add(listToAdd);
});
return fragArr;
}
I used a while loop to trim 0's instead of converting to int and converting back to a string for 2 reasons.
Time Complexity - If you convert data types for this problem, even using a Big Integer or by some other means, you're costing yourself efficiency. Refer to this post on the time complexity of converting to an int and back. Both parseInt and toString are O(n) operations where n is the entire length of the string. My while loop implementation is O(n) where n is the number of leading 0's.
Number Format Exception - If you are passed a string like "0000000000000000000001000000000000000000000", an exception would be thrown if you try to convert the value to an integer to trim the leading 0's because this value is too large for the integer data type in Java. So this is an edge case to consider.
Here's a unit test.
#Test
public void fragmentTest() {
assertEquals(
Arrays.asList(
Arrays.asList("abc", "123", "dce", "456"),
Arrays.asList("123", "abcde", "444", "a")
),
fragmentArr(new String[]{"abc123dce456", "123abcde444a"})
);
assertEquals(
Arrays.asList(
Arrays.asList("abc", "1000000000000000000000", "def", "29")
),
fragmentArr(new String[]{"abc0000000000000000000001000000000000000000000def29"})
);
}
newbie here. Any help with this problem would be appreciated:
You are given a String variable called data that contain letters and spaces only. Write the Java class to print a modified version of the String where all lowercase letters are replaced by ? and all whitespaces are replaced by +. An example is shown below: I Like Java becomes I+L???+J???.
What I have so far:
public static void main (String[] args) {
Scanner input = new Scanner(System.in);
String data;
//prompt
System.out.println("Enter a sentence: ");
//input
data = input.nextLine();
for (int i = 0; i < data.length(); i++) {
if (Character.isWhitespace(data.charAt(i))) {
data.replace("", "+");
if (Character.isLowerCase(data.charAt(i))) {
data.replace(i, i++, ); //not sure what to include here
}
} else {
System.out.print(data);
}
}
}
any suggestions would be appreciated.
You can do it in two steps by chaining String#replaceAll. In the first step, replace the regex, [a-z], with ?. The regex, [a-z] means a character from a to z.
public class Main {
public static void main(String[] args) {
String str = "I Like Java";
str = str.replaceAll("[a-z]", "?").replaceAll("\\s+", "+");
System.out.println(str);
}
}
Output:
I+L???+J???
Alternatively, you can use a StringBuilder to build the desired string. Instead of using a StringBuilder variable, you can use String variable but I recommend you use StringBuilder for such cases. The logic of building the desired string is simple:
Loop through all characters of the string and check if the character is a lowercase letter. If yes, append ? to the StringBuilder instance else if the character is whitespace, append + to the StringBuilder instance else append the character to the StringBuilder instance as it is.
Demo:
public class Main {
public static void main(String[] args) {
String str = "I Like Java";
StringBuilder sb = new StringBuilder();
int len = str.length();
for (int i = 0; i < len; i++) {
char ch = str.charAt(i);
if (Character.isLowerCase(ch)) {
sb.append('?');
} else if (Character.isWhitespace(ch)) {
sb.append('+');
} else {
sb.append(ch);
}
}
// Assign the result to str
str = sb.toString();
// Display str
System.out.println(str);
}
}
Output:
I+L???+J???
If the requirement states:
The first character of each word is a letter (uppercase or lowercase) which needs to be left as it is.
Second character onwards can be any word character which needs to be replaced with ?.
All whitespace characters of the string need to be replaced with +.
you can do it as follows:
Like the earlier solution, chain String#replaceAll for two steps. In the first step, replace the regex, (?<=\p{L})\w, with ?. The regex, (?<=\p{L})\w means:
\w specifies a word character.
(?<=\p{L}) specifies a positive lookbeghind for a letter i.e. \p{L}.
In the second step, simply replace one or more whitespace characters i.e. \s+ with +.
Demo:
public class Main {
public static void main(String[] args) {
String str = "I like Java";
str = str.replaceAll("(?<=\\p{L})\\w", "?").replaceAll("\\s+", "+");
System.out.println(str);
}
}
Output:
I+l???+J???
Alternatively, again like the earlier solution you can use a StringBuilder to build the desired string. Loop through all characters of the string and check if the character is a letter. If yes, append it to the StringBuilder instance and then loop through the remaining characters until all characters are exhausted or a space character is encountered. If a whitespace character is encountered, append + to the StringBuilder instance else append ? to it.
Demo:
public class Main {
public static void main(String[] args) {
String str = "I like Java";
StringBuilder sb = new StringBuilder();
int len = str.length();
for (int i = 0; i < len; i++) {
char ch = str.charAt(i++);
if (Character.isLetter(ch)) {
sb.append(ch);
while (i < len && !Character.isWhitespace(ch = str.charAt(i))) {
sb.append('?');
i++;
}
if (Character.isWhitespace(ch)) {
sb.append('+');
}
}
}
// Assign the result to str
str = sb.toString();
// Display str
System.out.println(str);
}
}
Output:
I+l???+J???
package com.company;
import java.util.*;
public class dat {
public static void main(String[] args) {
System.out.println("enter the string:");
Scanner ss = new Scanner(System.in);
String data = ss.nextLine();
for (int i = 0; i < data.length(); i++) {
char ch = data.charAt(i);
if (Character.isWhitespace(ch))
System.out.print("+");
else if (Character.isLowerCase(ch))
System.out.print("?");
else
System.out.print(ch);
}
}
}
enter the string:
i Love YouU
?+L???+Y??U
Firstly, you are trying to make changes to String object which is immutable. Simple way to achieve what you want is convert string to character array and loop over array items:
Scanner input = new Scanner(System.in);
String data;
//prompt
System.out.println("Enter a sentence: ");
//input
data = input.nextLine();
char[] dataArray = data.toCharArray();
for (int i = 0; i < dataArray.length; i++) {
if (Character.isWhitespace(dataArray[i])) {
dataArray[i] = '+';
} else if (Character.isLowerCase(dataArray[i])) {
dataArray[i] = '?';
}
}
System.out.print(dataArray);
See the below code and figure out what's wrong in your code. To include multiple regex put the char within square brackets:
import java.util.Scanner;
public class mainClass {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter a sentence: ");
String data = input.nextLine();
String one = data.replaceAll(" ", "+");
String two = one.replaceAll("[a-z]", "?");
System.out.println(two);
}
}
You can use String.codePoints method to get a stream over int values of characters of this string, and process them:
private static String replaceCharacters(String str) {
return str.codePoints()
.map(ch -> {
if (Character.isLowerCase(ch))
return '?';
if (Character.isWhitespace(ch))
return '+';
return ch;
})
.mapToObj(Character::toString)
.collect(Collectors.joining());
}
public static void main(String[] args) {
System.out.println(replaceCharacters("Lorem ipsum")); // L????+?????
System.out.println(replaceCharacters("I Like Java")); // I+L???+J???
}
See also: Replace non ASCII character from string
and thank you for helping me.
So my question is i need a code that asks you for a String like "1234 567" (input), then returns the string numbers like "1 2 3 4 5 6 7" (output) once more
my current code is:
public class StringComEspaços {
public static String formatNumberWithSpaces(String inputString) {
String outputString = "222";
return outputString;
}
public static void main(String[] args) {
System.out.println(formatNumberWithSpaces("123 222 2222"));
}
}
thanks for the help, and sorry for bad english :).
There are many possible ways to solve your problem.
You can do it in an OO way with StringBuilder:
public static String formatNumberWithSpaces(String inputString) {
StringBuilder output = new StringBuilder();
for (char c : inputString.toCharArray()) // Iterate over every char
if (c != ' ') // Get rid of spaces
output.append(c).append(' '); // Append the char and a space
return output.toString();
}
Which you can also do with a String instead of the StringBuilder by simply using the + operator instead of the .append() method.
Or you can do it a more "modern" way by using Java 8 features - which in my opinion is fun doing, but not the best way - e.g. like this:
public static String formatNumberWithSpaces(String inputString) {
return Arrays.stream(input.split("")) // Convert to stream of every char
.map(String::trim) // Convert spaces to empty strings
.filter(s -> !s.isEmpty()) // Remove empty strings
.reduce((l, r) -> l + " " + r) // build the new string with spaces between every character
.get(); // Get the actual string from the optional
}
Just try something that works for you.
Try out this function:
public static String formatNumberWithSpaces(String inputString){
String outputString = ""; //Declare an empty String
for (int i = 0;i < inputString.length(); i++){ //Iterate through the String passed as function argument
if (inputString.charAt(i) != ' '){ //Use the charAt function which returns the char representation of specified string index(i variable)
outputString+=inputString.charAt(i); //Same as 'outputString = outputString + inputString.charAt(i);'. So now we collect the char and append it to empty string
outputString+=' '; //We need to separate the next char using ' '
} //We do above instruction in loop till the end of string is reached
}
return outputString.substring(0, outputString.length()-1);
}
Just call it by:
System.out.println(formatNumberWithSpaces("123 222 2222"));
EDIT:
Or if you want to ask user for input, try:
Scanner in = new Scanner(System.in);
System.out.println("Give me your string to parse");
String input = in.nextLine(); //it moves the scanner position to the next line and returns the value as a string.
System.out.println(formatNumberWithSpaces(input)); // Here you print the returned value of formatNumberWithSpaces function
Don't forget to import, so you will be able to read user input :
import java.util.Scanner;
There are various ways to read input from the keyboard, the java.util.Scanner class is one of them.
EDIT2:
I changed:
return outputString;
..to: return outputString.substring(0, outputString.length()-1);
Just because outputString+=' '; was also appending empty space at the end of string, which is useless. Didn't add an if inside for loop which wouldn't add space when last char is parsed, just because of its low performance inside for loop.
use this code.
public class StringComEspaços {
public static void main(String[] args) {
System.out.println(formatNumberWithSpaces("123 222 2222"));
}
private static String formatNumberWithSpaces(String string) {
String lineWithoutSpaces = string.replaceAll("\\s+", "");
String[] s = lineWithoutSpaces.split("");
String os = "";
for (int i = 0; i < s.length; i++) {
os = os + s[i] + " ";
}
return os;
}
}
Language : Java
Key Notes: *Needs to loop through a String using either a For loop or While loop
*It removes the duplicate letter(s) of the String and returns the word without the dupilcates.
Eg: The string is HELLO - The method then loops through and removes any duplicates, in this case " L " and returns in the end HELO
i have this so far
private String removeAnyDuplicates(String userWord)
{
//Code goes here?
return "" ; // Need to return the new string
}
You can do that with regular expressions. e.g.:
private static final Pattern REGEX_PATTERN =
Pattern.compile("(.)\\1*");
public static void main(String[] args) {
String input = "HELLO, AABBCC";
System.out.println(
REGEX_PATTERN.matcher(input).replaceAll("$1")
); // prints "HELO, ABC"
}
I'm assuming that removing duplicates means that the result contains at most one occurrence of any character. (Some of the other answers assume that adjacent duplicates only need to be reduced to single occurrences.) The basic algorithm would be:
initialize the result to the empty string
loop through each character of the input and if the character is not already present in the result, append it to the result
return the result
A naive (and very inefficient) implementation would be:
private String removeAnyDuplicates(String userWord)
{
String result = "";
for (int i = 0; i < userWord.length(); ++i) {
char c = result.charAt(i);
if (result.indexOf(c) < 0) {
// negative index indicates not present
result += String.valueOf(c);
}
}
return result;
}
This has two major sources of inefficiency: it creates many intermediate String objects and it has to scan the entire result so far for each character of the input. These problems can be solved by using some other built-in Java classes—a StringBuilder to more efficiently accumulate the result and a Set implementation to efficiently record and test which characters have already been seen:
private String removeAnyDuplicates(String userWord)
{
int len = userWord.length();
StringBuilder result = new StringBuilder(len);
Set<Character> unique = new HashSet<Character>();
for (int i = 0; i < len; ++i) {
char c = result.charAt(i);
// try to add c to set of unique characters
if (unique.add(c)) {
// if it succeeds, this is the first time seeing c
result.append(c);
}
}
return result.toString();
}
private String removeAnyDuplicates(String userWord)
{
CharSequence inputStr = userWord;
int length = inputStr.length();
Set<Character> uniqueChars = new HashSet<Character>();
for(int i=0; i < length; ++i) {
uniqueChars.add(inputStr.charAt(i));
}
return uniqueChars.size() >= 3;
}
check out this answer
Convert the string to an array of char, and store it in a LinkedHashSet. That will preserve your ordering, and remove duplicates.
Like this:
private static String removeAnyDuplicates(String userWord)
{
char[] chars = userWord.toCharArray();
Set<Character> charSet = new LinkedHashSet<Character>();
for (char c : chars) {
charSet.add(c);
}
StringBuilder sb = new StringBuilder();
for (Character character : charSet) {
sb.append(character);
}
return sb.toString();
}
Remember:
import java.util.LinkedHashSet;
import java.util.Set;
You can try this
public static void main(String args[]){
System.out.println(removeAnyDuplicates("HELLO"));
}
private static String removeAnyDuplicates(String userWord)
{
char[] arr=userWord.toCharArray();
List<String> list=new ArrayList<>();
for(int i=0;i<arr.length;i++){
if(!list.contains(String.valueOf(arr[i]))){
list.add(String.valueOf(arr[i]));
}
}
return list.toString().replaceAll("\\[|\\]|\\,","") ;
}
Try this one liner:
private String removeAnyDuplicates(String userWord) {
return userWord.replaceAll("(.)\\1+", "$1");
}
This uses a regular expression to find repeated (2 or more) letters and replaces them with a single instance of the letter.
It is unclear if "repeated" means appearing immediately after or anywhere after. For anywhere, use this:
private String removeAnyDuplicates(String userWord) {
return userWord.replaceAll("(.)(?=.*\\1)", "");
}
I am trying to iterate through a string in order to remove the duplicates characters.
For example the String aabbccdef should become abcdef
and the String abcdabcd should become abcd
Here is what I have so far:
public class test {
public static void main(String[] args) {
String input = new String("abbc");
String output = new String();
for (int i = 0; i < input.length(); i++) {
for (int j = 0; j < output.length(); j++) {
if (input.charAt(i) != output.charAt(j)) {
output = output + input.charAt(i);
}
}
}
System.out.println(output);
}
}
What is the best way to do this?
Convert the string to an array of char, and store it in a LinkedHashSet. That will preserve your ordering, and remove duplicates. Something like:
String string = "aabbccdefatafaz";
char[] chars = string.toCharArray();
Set<Character> charSet = new LinkedHashSet<Character>();
for (char c : chars) {
charSet.add(c);
}
StringBuilder sb = new StringBuilder();
for (Character character : charSet) {
sb.append(character);
}
System.out.println(sb.toString());
Using Stream makes it easy.
noDuplicates = Arrays.asList(myString.split(""))
.stream()
.distinct()
.collect(Collectors.joining());
Here is some more documentation about Stream and all you can do with
it :
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
The 'description' part is very instructive about the benefits of Streams.
Try this simple solution:
public String removeDuplicates(String input){
String result = "";
for (int i = 0; i < input.length(); i++) {
if(!result.contains(String.valueOf(input.charAt(i)))) {
result += String.valueOf(input.charAt(i));
}
}
return result;
}
I would use the help of LinkedHashSet. Removes dups (as we are using a Set, maintains the order as we are using linked list impl). This is kind of a dirty solution. there might be even a better way.
String s="aabbccdef";
Set<Character> set=new LinkedHashSet<Character>();
for(char c:s.toCharArray())
{
set.add(Character.valueOf(c));
}
Create a StringWriter. Run through the original string using charAt(i) in a for loop. Maintain a variable of char type keeping the last charAt value. If you iterate and the charAt value equals what is stored in that variable, don't add to the StringWriter. Finally, use the StringWriter.toString() method and get a string, and do what you need with it.
Here is an improvement to the answer by Dave.
It uses HashSet instead of the slightly more costly LinkedHashSet, and reuses the chars buffer for the result, eliminating the need for a StringBuilder.
String string = "aabbccdefatafaz";
char[] chars = string.toCharArray();
Set<Character> present = new HashSet<>();
int len = 0;
for (char c : chars)
if (present.add(c))
chars[len++] = c;
System.out.println(new String(chars, 0, len)); // abcdeftz
Java 8 has a new String.chars() method which returns a stream of characters in the String. You can use stream operations to filter out the duplicate characters like so:
String out = in.chars()
.mapToObj(c -> Character.valueOf((char) c)) // bit messy as chars() returns an IntStream, not a CharStream (which doesn't exist)
.distinct()
.map(Object::toString)
.collect(Collectors.joining(""));
String input = "AAAB";
String output = "";
for (int index = 0; index < input.length(); index++) {
if (input.charAt(index % input.length()) != input
.charAt((index + 1) % input.length())) {
output += input.charAt(index);
}
}
System.out.println(output);
but you cant use it if the input has the same elements, or if its empty!
Code to remove the duplicate characters in a string without using any additional buffer. NOTE: One or two additional variables are fine. An extra array is not:
import java.util.*;
public class Main{
public static char[] removeDupes(char[] arr){
if (arr == null || arr.length < 2)
return arr;
int len = arr.length;
int tail = 1;
for(int x = 1; x < len; x++){
int y;
for(y = 0; y < tail; y++){
if (arr[x] == arr[y]) break;
}
if (y == tail){
arr[tail] = arr[x];
tail++;
}
}
return Arrays.copyOfRange(arr, 0, tail);
}
public static char[] bigArr(int len){
char[] arr = new char[len];
Random r = new Random();
String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$%^&*()-=_+[]{}|;:',.<>/?`~";
for(int x = 0; x < len; x++){
arr[x] = alphabet.charAt(r.nextInt(alphabet.length()));
}
return arr;
}
public static void main(String args[]){
String result = new String(removeDupes(new char[]{'a', 'b', 'c', 'd', 'a'}));
assert "abcd".equals(result) : "abcda should return abcd but it returns: " + result;
result = new String(removeDupes(new char[]{'a', 'a', 'a', 'a'}));
assert "a".equals(result) : "aaaa should return a but it returns: " + result;
result = new String(removeDupes(new char[]{'a', 'b', 'c', 'a'}));
assert "abc".equals(result) : "abca should return abc but it returns: " + result;
result = new String(removeDupes(new char[]{'a', 'a', 'b', 'b'}));
assert "ab".equals(result) : "aabb should return ab but it returns: " + result;
result = new String(removeDupes(new char[]{'a'}));
assert "a".equals(result) : "a should return a but it returns: " + result;
result = new String(removeDupes(new char[]{'a', 'b', 'b', 'a'}));
assert "ab".equals(result) : "abba should return ab but it returns: " + result;
char[] arr = bigArr(5000000);
long startTime = System.nanoTime();
System.out.println("2: " + new String(removeDupes(arr)));
long endTime = System.nanoTime();
long duration = (endTime - startTime);
System.out.println("Program took: " + duration + " nanoseconds");
System.out.println("Program took: " + duration/1000000000 + " seconds");
}
}
How to read and talk about the above code:
The method called removeDupes takes an array of primitive char called arr.
arr is returned as an array of primitive characters "by value". The arr passed in is garbage collected at the end of Main's member method removeDupes.
The runtime complexity of this algorithm is O(n) or more specifically O(n+(small constant)) the constant being the unique characters in the entire array of primitive chars.
The copyOfRange does not increase runtime complexity significantly since it only copies a small constant number of items. The char array called arr is not stepped all the way through.
If you pass null into removeDupes, the method returns null.
If you pass an empty array of primitive chars or an array containing one value, that unmodified array is returned.
Method removeDupes goes about as fast as physically possible, fully utilizing the L1 and L2 cache, so Branch redirects are kept to a minimum.
A 2015 standard issue unburdened computer should be able to complete this method with an primitive char array containing 500 million characters between 15 and 25 seconds.
Explain how this code works:
The first part of the array passed in is used as the repository for the unique characters that are ultimately returned. At the beginning of the function the answer is: "the characters between 0 and 1" as between 0 and tail.
We define the variable y outside of the loop because we want to find the first location where the array index that we are looking at has been duplicated in our repository. When a duplicate is found, it breaks out and quits, the y==tail returns false and the repository is not contributed to.
when the index x that we are peeking at is not represented in our repository, then we pull that one and add it to the end of our repository at index tail and increment tail.
At the end, we return the array between the points 0 and tail, which should be smaller or equal to in length to the original array.
Talking points exercise for coder interviews:
Will the program behave differently if you change the y++ to ++y? Why or why not.
Does the array copy at the end represent another 'N' pass through the entire array making runtime complexity O(n*n) instead of O(n) ? Why or why not.
Can you replace the double equals comparing primitive characters with a .equals? Why or why not?
Can this method be changed in order to do the replacements "by reference" instead of as it is now, "by value"? Why or why not?
Can you increase the efficiency of this algorithm by sorting the repository of unique values at the beginning of 'arr'? Under which circumstances would it be more efficient?
public class RemoveRepeated4rmString {
public static void main(String[] args) {
String s = "harikrishna";
String s2 = "";
for (int i = 0; i < s.length(); i++) {
Boolean found = false;
for (int j = 0; j < s2.length(); j++) {
if (s.charAt(i) == s2.charAt(j)) {
found = true;
break; //don't need to iterate further
}
}
if (found == false) {
s2 = s2.concat(String.valueOf(s.charAt(i)));
}
}
System.out.println(s2);
}
}
public static void main(String a[]){
String name="Madan";
System.out.println(name);
StringBuilder sb=new StringBuilder(name);
for(int i=0;i<name.length();i++){
for(int j=i+1;j<name.length();j++){
if(name.charAt(i)==name.charAt(j)){
sb.deleteCharAt(j);
}
}
}
System.out.println("After deletion :"+sb+"");
}
import java.util.Scanner;
public class dublicate {
public static void main(String... a) {
System.out.print("Enter the String");
Scanner Sc = new Scanner(System.in);
String st=Sc.nextLine();
StringBuilder sb=new StringBuilder();
boolean [] bc=new boolean[256];
for(int i=0;i<st.length();i++)
{
int index=st.charAt(i);
if(bc[index]==false)
{
sb.append(st.charAt(i));
bc[index]=true;
}
}
System.out.print(sb.toString());
}
}
To me it looks like everyone is trying way too hard to accomplish this task. All we are concerned about is that it copies 1 copy of each letter if it repeats. Then because we are only concerned if those characters repeat one after the other the nested loops become arbitrary as you can just simply compare position n to position n + 1. Then because this only copies things down when they're different, to solve for the last character you can either append white space to the end of the original string, or just get it to copy the last character of the string to your result.
String removeDuplicate(String s){
String result = "";
for (int i = 0; i < s.length(); i++){
if (i + 1 < s.length() && s.charAt(i) != s.charAt(i+1)){
result = result + s.charAt(i);
}
if (i + 1 == s.length()){
result = result + s.charAt(i);
}
}
return result;
}
String str1[] ="Hi helloo helloo oooo this".split(" ");
Set<String> charSet = new LinkedHashSet<String>();
for (String c: str1)
{
charSet.add(c);
}
StringBuilder sb = new StringBuilder();
for (String character : charSet)
{
sb.append(character);
}
System.out.println(sb.toString());
I think working this way would be more easy,,,
Just pass a string to this function and the job is done :) .
private static void removeduplicate(String name)
{ char[] arr = name.toCharArray();
StringBuffer modified =new StringBuffer();
for(char a:arr)
{
if(!modified.contains(Character.toString(a)))
{
modified=modified.append(Character.toString(a)) ;
}
}
System.out.println(modified);
}
public class RemoveDuplicatesFromStingsMethod1UsingLoops {
public static void main(String[] args) {
String input = new String("aaabbbcccddd");
String output = "";
for (int i = 0; i < input.length(); i++) {
if (!output.contains(String.valueOf(input.charAt(i)))) {
output += String.valueOf(input.charAt(i));
}
}
System.out.println(output);
}
}
output: abcd
You can't. You can create a new String that has duplicates removed. Why aren't you using StringBuilder (or StringBuffer, presumably)?
You can run through the string and store the unique characters in a char[] array, keeping track of how many unique characters you've seen. Then you can create a new String using the String(char[], int, int) constructor.
Also, the problem is a little ambiguous—does “duplicates” mean adjacent repetitions? (In other words, what should happen with abcab?)
Oldschool way (as we wrote such a tasks in Apple ][ Basic, adapted to Java):
int i,j;
StringBuffer str=new StringBuffer();
Scanner in = new Scanner(System.in);
System.out.print("Enter string: ");
str.append(in.nextLine());
for (i=0;i<str.length()-1;i++){
for (j=i+1;j<str.length();j++){
if (str.charAt(i)==str.charAt(j))
str.deleteCharAt(j);
}
}
System.out.println("Removed non-unique symbols: " + str);
Here is another logic I'd like to share. You start comparing from midway of the string length and go backward.
Test with:
input = "azxxzy";
output = "ay";
String removeMidway(String input){
cnt = cnt+1;
StringBuilder str = new StringBuilder(input);
int midlen = str.length()/2;
for(int i=midlen-1;i>0;i--){
for(int j=midlen;j<str.length()-1;j++){
if(str.charAt(i)==str.charAt(j)){
str.delete(i, j+1);
midlen = str.length()/2;
System.out.println("i="+i+",j="+j+ ",len="+ str.length() + ",midlen=" + midlen+ ", after deleted = " + str);
}
}
}
return str.toString();
}
Another possible solution, in case a string is an ASCII string, is to maintain an array of 256 boolean elements to denote ASCII character appearance in a string. If a character appeared for the first time, we keep it and append to the result. Otherwise just skip it.
public String removeDuplicates(String input) {
boolean[] chars = new boolean[256];
StringBuilder resultStringBuilder = new StringBuilder();
for (Character c : input.toCharArray()) {
if (!chars[c]) {
resultStringBuilder.append(c);
chars[c] = true;
}
}
return resultStringBuilder.toString();
}
This approach will also work with Unicode string. You just need to increase chars size.
Solution using JDK7:
public static String removeDuplicateChars(final String str){
if (str == null || str.isEmpty()){
return str;
}
final char[] chArray = str.toCharArray();
final Set<Character> set = new LinkedHashSet<>();
for (char c : chArray) {
set.add(c);
}
final StringBuilder sb = new StringBuilder();
for (Character character : set) {
sb.append(character);
}
return sb.toString();
}
String str = "eamparuthik#gmail.com";
char[] c = str.toCharArray();
String op = "";
for(int i=0; i<=c.length-1; i++){
if(!op.contains(c[i] + ""))
op = op + c[i];
}
System.out.println(op);
public static String removeDuplicateChar(String str){
char charArray[] = str.toCharArray();
StringBuilder stringBuilder= new StringBuilder();
for(int i=0;i<charArray.length;i++){
int index = stringBuilder.toString().indexOf(charArray[i]);
if(index <= -1){
stringBuilder.append(charArray[i]);
}
}
return stringBuilder.toString();
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class RemoveDuplicacy
{
public static void main(String args[])throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter any word : ");
String s = br.readLine();
int l = s.length();
char ch;
String ans=" ";
for(int i=0; i<l; i++)
{
ch = s.charAt(i);
if(ch!=' ')
ans = ans + ch;
s = s.replace(ch,' '); //Replacing all occurrence of the current character by a space
}
System.out.println("Word after removing duplicate characters : " + ans);
}
}
public static void main(String[] args) {
int i,j;
StringBuffer str=new StringBuffer();
Scanner in = new Scanner(System.in);
System.out.print("Enter string: ");
str.append(in.nextLine());
for (i=0;i<str.length()-1;i++)
{
for (j=1;j<str.length();j++)
{
if (str.charAt(i)==str.charAt(j))
str.deleteCharAt(j);
}
}
System.out.println("Removed String: " + str);
}
This is improvement on solution suggested by #Dave. Here, I am implementing in single loop only.
Let's reuse the return of set.add(T item) method and add it simultaneously in StringBuffer if add is successfull
This is just O(n). No need to make a loop again.
String string = "aabbccdefatafaz";
char[] chars = string.toCharArray();
StringBuilder sb = new StringBuilder();
Set<Character> charSet = new LinkedHashSet<Character>();
for (char c : chars) {
if(charSet.add(c) ){
sb.append(c);
}
}
System.out.println(sb.toString()); // abcdeftz
Simple solution is to iterate through the given string and put each unique character into another string(in this case, a variable result ) if this string doesn't contain that particular character.Finally return result string as output.
Below is working and tested code snippet for removing duplicate characters from the given string which has O(n) time complexity .
private static String removeDuplicate(String s) {
String result="";
for (int i=0 ;i<s.length();i++) {
char ch = s.charAt(i);
if (!result.contains(""+ch)) {
result+=""+ch;
}
}
return result;
}
If the input is madam then output will be mad.
If the input is anagram then output will be angrm
Hope this helps.
Thanks
For the simplicity of the code- I have taken hardcore input, one can take input by using Scanner class also
public class KillDuplicateCharInString {
public static void main(String args[]) {
String str= "aaaabccdde ";
char arr[]= str.toCharArray();
int n = arr.length;
String finalStr="";
for(int i=0;i<n;i++) {
if(i==n-1){
finalStr+=arr[i];
break;
}
if(arr[i]==arr[i+1]) {
continue;
}
else {
finalStr+=arr[i];
}
}
System.out.println(finalStr);
}
}
public static void main (String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
String str = "";
char c;
for(int i = 0; i < s.length(); i++)
{
c = s.charAt(i);
str = str + c;
s = s.replace(c, ' ');
if(i == s.length() - 1)
{
System.out.println(str.replaceAll("\\s", ""));
}
}
}
package com.st.removeduplicate;
public class RemoveDuplicate {
public static void main(String[] args) {
String str1="shushil",str2="";
for(int i=0; i<=str1.length()-1;i++) {
int count=0;
for(int j=0;j<=i;j++) {
if(str1.charAt(i)==str1.charAt(j))
count++;
if(count >1)
break;
}
if(count==1)
str2=str2+str1.charAt(i);
}
System.out.println(str2);
}
}