Delete element last occurrence in array - java

If a row of an array had the characters:
line = "I appreciate you helping me out!"
Let's say I wanted to delete the last occurrence of the letter 'e'.
How?
i.e. the result should be:
"I appreciate you helping m out!"
Here is my idea and I know the syntax is wrong. I start at 26 because that's the last time position an 'e' happens in the length of the string.
for (int i = 26; i < line.length() ; i++)
line.chars('e') = (line.chars('') && line.chars(i));
}

String line = "I appreciate you helping me out!";
int index = line.lastIndexOf('e');
if(index != -1) //prevent IndexOutOfBoundsException in case it can't find the char
line = new StringBuilder(line).deleteCharAt(index).toString();
or
String line = "I appreciate you helping me out!";
for (int i = line.length(); --i >= 0;){
if(line.charAt(i) == 'e'){
line = line.substring(0, i) + line.substring(i + 1);
break;
}
}

Or you can use regular expression like below :
String word = "I appreciate you helping me out!";
System.out.println(word.replaceAll("[e]([^e]*)$","$1"));
Out-put :
I appreciate you helping m out!

please try the below code snippet. Ideally it should work in generic way.
StringBuilder line = new StringBuilder(
"I appreciate you helping me out!");
System.out.println("Given input String :" + line);
int lastOccuranceIndex = 0;
int deleteIndex = 0;
char[] charr = line.toString().toLowerCase().toCharArray();
Map<Character, List<Integer>> charMap = new LinkedHashMap<Character, List<Integer>>();
List<Integer> indexList = null;
for (int i = 0; i < charr.length; i++) {
if (charMap.containsKey(charr[i])) {
indexList = charMap.get(charr[i]);
indexList.add(i);
charMap.put(charr[i], indexList);
} else if (Character.isAlphabetic(charr[i])) {
indexList = new ArrayList<Integer>();
indexList.add(i);
charMap.put(charr[i], indexList);
}
}
for (Entry<Character, List<Integer>> entry : charMap.entrySet()) {
indexList = entry.getValue();
if (indexList.size() > 2) {
// System.out.println(entry.getKey()
// +" last but one : "+indexList.get(indexList.size() -2));
if (indexList.get(indexList.size() - 2) > lastOccuranceIndex) {
lastOccuranceIndex = indexList.get(indexList.size() - 2);
deleteIndex = indexList.get(indexList.size() - 1);
}
}
}
System.out.println("last occurance character index "
+ lastOccuranceIndex + " and the character to delete is :"
+ charr[lastOccuranceIndex]);
char deleteChar = line.charAt(deleteIndex);
System.out.println("deleteChar :" + deleteChar + " at index :"
+ deleteIndex);
line = line.deleteCharAt(deleteIndex);
System.out.println("String content after delete operation : " + line);
output:
Given input String :I appreciate you helping me out!
last occurance character index 18 and the character to delete is :e
deleteChar :e at index :26
String content after delete operation : I appreciate you helping m out!

Regex to the rescue:
line = line.replaceAll("e(?=[^e]*$)", "");
The regex (?=[^e]*$) is a look ahead the requires there to be no occurrences of e anywhere after the e being matched.

Related

How do i take a string of letters (user input) and separate all duplicate characters with X's?

System.out.print("Enter the message to encrypt: ");
message = s.next().toString(); // this message is inserted
List<String> strings = new ArrayList<String>();
int index = 0;
while (index < message.length())
{
strings.add(message.substring(index, Math.min(index + 2,
message.length())));
// separates the list by two's. i.e. [ST, EV, EN] for "Steven"
index += 2;
}
System.out.println(strings); // prints out list
break; // end of case
/*
What I want to do with this code is separate duplicate characters by X's so that, for instance, if the name "William" was inserted, it would insert [WI, LX, LI, AM]. Also, if there is an odd number of letters (i.e. BOB), you would fill in the last number with an "X" to make it a pair: [BO, BX]
I have searched stack overflow consistently and cannot find an answer so any advice is greatly appreciated!
*/
Here the condition in the while loop should be
while (index+2 < message.length())
or else it might lead to index out of bound exception.
First you have to create the string with replaced "X".
Then put that in the loop
Scanner s = new Scanner(System.in);
String input = "";
String message = "";
System.out.print("Enter the message to encrypt: ");
input = s.next(); // this message is inserted
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0;i<input.length();i++){
if(i>0 && input.charAt(i) == input.charAt(i-1)){
stringBuilder.append("X");
stringBuilder.append(input.charAt(i));
}else{
stringBuilder.append(input.charAt(i));
}
}
if ( (stringBuilder.length() & 1) != 0 ) {
stringBuilder.append("X");
}
message = stringBuilder.toString();
List<String> strings = new ArrayList<String>();
int index = 0;
while (index < message.length())
{
strings.add(message.substring(index, Math.min(index + 2,
message.length())));
// separates the list by two's. i.e. [ST, EV, EN] for "Steven"
index += 2;
}
System.out.println(strings); // prints out list
You can do it by simply checking that if the substring is made of same characters then you can take the first character and concatenate it with 'X' and add it to the list and increase the index by 1. Else just add the substring in the list and increase the index by 2. Below is my modified while loop:
while (index < message.length())
{
//strings.add(message.substring(index, Math.min(index + 2, message.length())));
String str = message.substring(index, Math.min(index + 2,
message.length()));
// separates the list by two's. i.e. [ST, EV, EN] for "Steven"
if(str.length() == 1 || str.charAt(0) == str.charAt(1)) {
strings.add(str.charAt(0) + "X");
index += 1;
}
else{
strings.add(str);
index += 2;
}
}

How to count white spaces in a given argument?

I find it strange why spaceCount doesn't add up when the expression is "12 + 1". I get an output 0 for spaceCount even though it should be 2. Any insight would be appreciated!
public int countSpaces(String expr) {
String tok = expr;
int spaceCount = 0;
String delimiters = "+-*/#! ";
StringTokenizer st = new StringTokenizer(expr, delimiters, true);
while (st.hasMoreTokens()) {
if ((tok = st.nextToken()).equals(" ")) {
spaceCount++;
}
}
return spaceCount; // the expression is: 12 + 1, so this should return 2, but it returns 0;
}
Your code seems to be ok, but if you want to count spaces you can use this :
int count = str.length() - str.replace(" ", "").length();
A tokenizer is overkill (and doesn't really help you) for this problem. Just loop through all the characters and count the spaces:
public int countSpaces( String expr )
{
int count = 0;
for( int i = 0; i < expr.length(); ++i )
{
if( expr.charAt(i) == ' ' )
++count;
}
return count;
}
Another one line solution could be the following which also performs a NULL check to the string.
int spacesCount = str == null ? 0 : str.length() - str.replace(" ", "").length();
Can also use:
String[] strArr = st.split(" ");
if (strArr.length > 1){
int countSpaces = strArr.length - 1;
}
This will find white spaces, including special ones.
You can keep the pattern so you don't need to compile it every time. If just need to search for " ", a loop should do it instead.
Matcher spaces = Pattern.compile("\\s").matcher(argumentString);
int count = 0;
while (spaces.find()) {
count++;
}

Java Unicode Characters

I'm familiar with problems with ascii. The problem is I have no experience with same problems in unicode characters. For example, how to return the word that occurs most frequently given a string array containing words? Thanks in advance!
p.s.: You can always use an array which length is "256" to represent all the characters in ASCII while you can't do that when it comes to unicode. Is HashMap a must and the best way to solve the problem? I heard that there are better ways to solve it. Below is what I can think of:
String str = "aa df ds df df"; // assume they are Unicode
String[] words = str.split(" ");
HashMap<String, Integer> map = new HashMap<String, Integer>();
for (String word : words){
if (map.containsKey(word)){
int f = map.get(word);
map.put(word, f+1);
} else{
map.put(word, 1);
}
}
int max = 0;
String maxWord = "";
for (String word : words){
int f = map.get(word);
if (f > max){
max = f;
maxWord = word;
}
}
System.out.println(maxWord + " " +max);
// Inspired by GameKyuubi. It can be solved using array sort and count the most frequently used word using constatnt space.
Arrays.sort(words);
int max = 0;
int count = 0;
String maxWord = "";
String prev = "";
for (String word : words){
if (prev.equals("") || word.equals(prev)){
count++;
} else{
count = 1;
}
if (max < count){
max = count;
maxWord = word;
}
prev = word;
}
System.out.println(maxWord + " " +max);

Compression algorithm in java

My goal is to write a program that compresses a string, for example:
input: hellooopppppp!
output:he2l3o6p!
Here is the code I have so far, but there are errors.
When I have the input: hellooo
my code outputs: hel2l3o
instead of: he213o
the 2 is being printed in the wrong spot, but I cannot figure out how to fix this.
Also, with an input of: hello
my code outputs: hel2l
instead of: he2lo
It skips the last letter in this case all together, and the 2 is also in the wrong place, an error from my first example.
Any help is much appreciated. Thanks so much!
public class compressionTime
{
public static void main(String [] args)
{
System.out.println ("Enter a string");
//read in user input
String userString = IO.readString();
//store length of string
int length = userString.length();
System.out.println(length);
int count;
String result = "";
for (int i=1; i<=length; i++)
{
char a = userString.charAt(i-1);
count = 1;
if (i-2 >= 0)
{
while (i<=length && userString.charAt(i-1) == userString.charAt(i-2))
{
count++;
i++;
}
System.out.print(count);
}
if (count==1)
result = result.concat(Character.toString(a));
else
result = result.concat(Integer.toString(count).concat(Character.toString(a)));
}
IO.outputStringAnswer(result);
}
}
I would
count from 0 as that is how indexes work in Java. Your code will be simpler.
would compare the current char to the next one. This will avoid printing the first character.
wouldn't compress ll as 2l as it is no smaller. Only sequences of at least 3 will help.
try to detect if a number 3 to 9 has been used and at least print an error.
use the debugger to step through the code to understand what it is doing and why it doesn't do what you think it should.
I am doing it this way. Very simple:
public static void compressString (String string) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < string.length(); i++) {
int count = 1;
while (i + 1 < string.length()
&& string.charAt(i) == string.charAt(i + 1)) {
count++;
i++;
}
if (count > 1) {
stringBuffer.append(count);
}
stringBuffer.append(string.charAt(i));
}
System.out.println("Compressed string: " + stringBuffer);
}
You can accomplish this using a nested for loops and do something simial to:
count = 0;
String results = "";
for(int i=0;i<userString.length();){
char begin = userString.charAt(i);
//System.out.println("begin is: "+begin);
for(int j=i+1; j<userString.length();j++){
char next = userString.charAt(j);
//System.out.println("next is: "+next);
if(begin == next){
count++;
}
else{
System.out.println("Breaking");
break;
}
}
i+= count+1;
if(count>0){
String add = begin + "";
int tempcount = count +1;
results+= tempcount + add;
}
else{
results+= begin;
}
count=0;
}
System.out.println(results);
I tested this output with Hello and the result was He2lo
also tested with hellooopppppp result he2l3o6p
If you don't understand how this works, you should learn regular expressions.
public String rleEncodeString(String in) {
StringBuilder out = new StringBuilder();
Pattern p = Pattern.compile("((\\w)\\2*)");
Matcher m = p.matcher(in);
while(m.find()) {
if(m.group(1).length() > 1) {
out.append(m.group(1).length());
}
out.append(m.group(2));
}
return out.toString();
}
Try something like this:
public static void main(String[] args) {
System.out.println("Enter a string:");
Scanner IO = new Scanner(System.in);
// read in user input
String userString = IO.nextLine() + "-";
int length = userString.length();
int count = 0;
String result = "";
char new_char;
for (int i = 0; i < length; i++) {
new_char = userString.charAt(i);
count++;
if (new_char != userString.charAt(i + 1)) {
if (count != 1) {
result = result.concat(Integer.toString(count + 1));
}
result = result.concat(Character.toString(new_char));
count = 0;
}
if (userString.charAt(i + 1) == '-')
break;
}
System.out.println(result);
}
The problem is that your code checks if the previous letter, not the next, is the same as the current.
Your for loops basically goes through each letter in the string, and if it is the same as the previous letter, it figures out how many of that letter there is and puts that number into the result string. However, for a word like "hello", it will check 'e' and 'l' (and notice that they are preceded by 'h' and 'e', receptively) and think that there is no repeat. It will then get to the next 'l', and then see that it is the same as the previous letter. It will put '2' in the result, but too late, resulting in "hel2l" instead of "he2lo".
To clean up and fix your code, I recommend the following to replace your for loop:
int count = 1;
String result = "";
for(int i=0;i<length;i++) {
if(i < userString.length()-1 && userString.charAt(i) == userString.charAt(i+1))
count++;
else {
if(count == 1)
result += userString.charAt(i);
else {
result = result + count + userString.charAt(i);
count = 1;
}
}
}
Comment if you need me to explain some of the changes. Some are necessary, others optional.
Here is the solution for the problem with better time complexity:
public static void compressString (String string) {
LinkedHashSet<String> charMap = new LinkedHashSet<String>();
HashMap<String, Integer> countMap = new HashMap<String, Integer>();
int count;
String key;
for (int i = 0; i < string.length(); i++) {
key = new String(string.charAt(i) + "");
charMap.add(key);
if(countMap.containsKey(key)) {
count = countMap.get(key);
countMap.put(key, count + 1);
}
else {
countMap.put(key, 1);
}
}
Iterator<String> iterator = charMap.iterator();
String resultStr = "";
while (iterator.hasNext()) {
key = iterator.next();
count = countMap.get(key);
if(count > 1) {
resultStr = resultStr + count + key;
}
else{
resultStr = resultStr + key;
}
}
System.out.println(resultStr);
}

Replace strings in a long String:

I have the following string:
Where Are You [Employee Name]?
your have a [Shift] shift...
and a list of strings that contains:
1. Employee Name
2. Shift
I need to find the given strings in the list in the long string and replace them with another content (including the [ and ] characters).
So for example the first string is need to be change to:
Where Are You Jhon Green?
your have a morning shift...
Is there any simple way to do that? using IndexOf will give me the location of this string but how would I include the [ , ] charecters as well?
UPDATE:
This is the code I tested so far:
Scanner sc = new Scanner(smsText);
for (String s; (s = sc.findWithinHorizon("(?<=\\[).*?(?=\\])", 0)) != null;)
{
words.add(s);
}
for (int j = 0; j < words.size(); j++)
{
Log.d(TAG, "The value for column: "+words.get(j) +" is: "+ rowData.getValue(words.get(j)));
smsText.replaceFirst("\\[" + words.get(j) + "\\]", rowData.getValue(words.get(j)));
}
Log.d(TAG, "Final String is: "+ smsText);
which is not giving me the right result, the string are not replaced.
UPDATE2:
The solution that worked for me is:
Scanner sc = new Scanner(smsText);
for (String s; (s = sc.findWithinHorizon("(?<=\\[).*?(?=\\])", 0)) != null;)
{
columnNames.add(s);
}
for (int j = 0; j < columnNames.size(); j++)
{
Log.d(TAG, "The value for column: "+columnNames.get(j) +" is: "+ rowData.getValue(columnNames.get(j)));
smsText = smsText.replaceFirst("\\[" + columnNames.get(j) + "\\]", rowData.getValue(columnNames.get(j)));
}
Log.d(TAG, "Final String is: "+ smsText);
Thanks to all for your help.
String key = myColumns.getName();
s.replaceFirst("\\[" + key + "\\]", myReplacements.getReplacement(key));
You could also use indexOf, but with a replace function it's immediately clear what you're trying to do.
try this
String s = "Where Are You [Employee Name]? your have a [Shift] shift..";
Map<String, String> replacementMap = new HashMap<>();
replacementMap.put("[Employee Name]", "John Green");
replacementMap.put("[Shift]", "morning");
for(Entry<String, String> e : replacementMap.entrySet()) {
s = s.replace(e.getKey(), e.getValue());
}
System.out.println(s);
output
Where Are You John Green? your have a morning shift..
A general solution could look something like this:
String message = "Where are you [Employee Name]? You have a [Shift] shift!";
Map<String, String> variables = new HashMap<>();
variables.put("Employee Name", "John Green");
variables.put("Shift", "morning");
StringBuffer endResult = new StringBuffer();
Matcher m = Pattern.compile("\\[(.*?)\\]").matcher(message);
while (m.find()) {
m.appendReplacement(endResult, variables.get(m.group(1)));
}
m.appendTail(endResult);
System.out.println(endResult.toString());
i know regex is there but if you want to go for recursive function here it is
public string replaceString(string str, string[] values, int index)
{
if (str.IndexOf('[') == -1 || str.IndexOf(']') == -1 || index > values.Length-1)
return str;
else
return replaceString(str.Replace(str.Substring(str.IndexOf('['), (str.IndexOf(']') - str.IndexOf('['))+1), values[index]), values, ++index);
}
calling this method
string strforreplac = "Where Are You [Employee Name]? your have a [Shift] shift...]";
string[] strvalues = {"Emil","morning"};
string newstring = replaceString(strforreplac,strvalues,0);

Categories