How to print a string formatted properly - java

I am doing Test Driven Development.So I created a case that needs to send an array of strings to the function.That function will check if the array has any uppercase letter strings.If there is then it needs to print all the strings as "name , name, name and name are amazing".So before the last one it should be putting an "and".
It is sometimes giving me dead code error because there are other cases that might be interfering with the execution of this case.
Test Case
#Test
void testAcceptsAJumbleOfUpperCaseAndLowerCase() {
theAmazingPeter obj = new theAmazingPeter();
String[] arr = {"Peter","GUNEET"};
String result = obj.AmazingPerson(arr);
assertEquals("Peter, and GUNEET are amazing",result);
}
}
Statement
else {
for (int i = 0; i < names.length; i++) {
if (names.length >= 1 && names[i].equals(names[i].toUpperCase())) {
if (i > 0) {
sb.append(", ");
if (i == names.length - 1) {
sb.append("and ");
}
}
sb.append(names[i]);
}
System.out.println(sb.toString() + " are amazing");
}
String result = sb.toString() + " are amazing";
return result;
}

If it is needed to check if the string contains capital letter, it will need to be implemented as following:
StringBuffer sb = new StringBuffer();
char ch;
for (int i = 0; i < names.length; i++) {
if (Character.isUpperCase(names[i].charAt(0))) {
if (i == names.length - 1) {
sb.append(" and " + names[i]);
} else if (i == names.length - 2) {
sb.append(names[i]);
} else {
sb.append(names[i] + ", ");
}
}
}
System.out.println(sb.toString() + " are amazing");
String result = sb.toString() + " are amazing";
return result;

This line in your code is wrong:
if(names.length >= 1 && names[i].equals(names[i].toUpperCase()))
This if statement comes true only when all the letters of string are capital letters.
For example: if names[i] contains "Peter" then names[i].toUpperCase() equals "PETER" and the expression will return false. But what you want is accepting this string because it contains capital letter.
Instead doing this, you can use Character.isUpperCase(char) method.
public boolean containsUpper(String s){
for (int i = 0 ; i< s.length(); i++){
if(Character.isUpperCase(s.charAt(i)))
return true;
}
return false;
}
You may call this function for every string then continue.

Related

How to remove repeating code in this solution?

I have this code which compresses characters in the given string and replaces repeated adjacent characters with their count.
Consider the following example:
Input:
aaabbccdsa
Expecting output:
a3b2c2dsa
My code is working properly but I think repeating if condition can be removed.
public class Solution {
public static String getCompressedString(String str) {
String result = "";
char anch = str.charAt(0);
int count = 0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch == anch) {
count++;
} else {
if (count == 1) { // from here
result += anch;
} else {
result += anch + Integer.toString(count);
} // to here
anch = ch;
count = 1;
}
if (i == str.length() - 1) {
if (count == 1) { // from here
result += anch;
} else {
result += anch + Integer.toString(count);
} // to here
}
}
return result;
}
}
In this solution code below is repeated two times
if (count == 1) {
result += anch;
} else {
result += anch + Integer.toString(count);
}
Please, note, I don't want to use a separate method for repeating logic.
You could do away with the if statements.
public static String getCompressedString(String str) {
char[] a = str.toCharArray();
StringBuilder sb = new StringBuilder();
for(int i=0,j=0; i<a.length; i=j){
for(j=i+1;j < a.length && a[i] == a[j]; j++);
sb.append(a[i]).append(j-i==1?"":j-i);
}
return sb.toString();
}
}
You can do something like this:
public static String getCompressedString(String str) {
String result = "";
int count = 1;
for (int i = 0; i < str.length(); i++) {
if (i + 1 < str.length() && str.charAt(i) == str.charAt(i + 1)) {
count++;
} else {
if (count == 1) {
result += str.charAt(i);
} else {
result += str.charAt(i) + "" + count;
count = 1;
}
}
}
return result;
}
I got rid of the repeated code, and it do as intended.
You can use this approach as explained below:
Code:
public class Test {
public static void main(String[] args) {
String s = "aaabbccdsaccbbaaadsa";
char[] strArray = s.toCharArray();
char ch0 = strArray[0];
int counter = 0;
StringBuilder sb = new StringBuilder();
for(int i=0;i<strArray.length;i++){
if(ch0 == strArray[i]){//check for consecutive characters and increment the counter
counter++;
} else { // when character changes while iterating
sb.append(ch0 + "" + (counter > 1 ? counter : ""));
counter = 1; // reset the counter to 1
ch0 = strArray[i]; // reset the ch0 with the current character
}
if(i == strArray.length-1){// case for last element of the string
sb.append(ch0 + "" + (counter > 1 ? counter : ""));
}
}
System.out.println(sb);
}
}
Sample Input/Output:
Input:: aaabbccdsaccbbaaadsa
Output:: a3b2c2dsac2b2a3dsa
Input:: abcdaaaaa
Output:: abcda5
Since, the body of the else and second if is the same, so we can merge them by updating the condition. The updated body of the function will be:
String result = "";
char anch = str.charAt(0);
int count = 0;
char ch = str.charAt(0); // declare ch outside the loop, and initialize to avoid error
for (int i = 0; i < str.length(); i++) {
ch = str.charAt(i);
if (ch == anch) {
count++;
}
// check if the second condition is false, or if we are at the end of the string
if (ch != anch || i == str.length() - 1) {
if (count == 1) { // from here
result += anch;
} else {
result += anch + Integer.toString(count);
} // to here
anch = ch;
count = 1;
}
}
// add the condition
// if count is greater than or
// if the last character added already to the result
if (count > 1 || (len < 2 || result.charAt(len - 2) != ch)) {
result += ch;
}
return result;
Test Cases:
I have tested the solution on the following inputs:
aaabbccdsa -> a3b2c2dsa
aaab -> a3b
aaa -> a3
ab -> ab
aabbc -> a2b2c
Optional
If you want to make it shorter, you can update these 2 conditions.
if (count == 1) { // from here
result += anch;
} else {
result += anch + Integer.toString(count);
} // to here
as
result += anch;
if (count != 1) { // from here
result += count;// no need to convert (implicit conversion)
} // to here
Here's a single-statement solution using Stream API and regular expressions:
public static final Pattern GROUP_OF_ONE_OR_MORE = Pattern.compile("(.)\\1*");
public static String getCompressedString(String str) {
return GROUP_OF_ONE_OR_MORE.matcher(str).results()
.map(MatchResult::group)
.map(s -> s.charAt(0) + (s.length() == 1 ? "" : String.valueOf(s.length())))
.collect(Collectors.joining());
}
main()
public static void main(String[] args) {
System.out.println(getCompressedString("aaabbccdsa"));
System.out.println(getCompressedString("awswwwhhhp"));
}
Output:
a3b2c2dsa // "aaabbccdsa"
awsw3h3p // "awswwwhhhp"
How does it work
A regular expression "(.)\\1*" is capturing a group (.) of identical characters of length 1 or greater. Where . - denotes any symbol, and \\1 is a back reference to the group.
Method Matcher.results() "returns a stream of match results for each subsequence of the input sequence that matches the pattern".
The only thing left is to evaluate the length of each group and transform it accordingly before collecting into the resulting String.
Links:
A quick tutorial on Regular Expressions.
Official tutorials on lambda expressions and streams
You can use a function which has the following 3 parameters : result, anch, count .
something of this sort:
private static String extractedFunction(String result,int count, char anch) {
return count ==1 ? (result + anch) : (result +anch+Integer.toString(count) );
}
make a function call from those two points like this :
result = extractedFunction(result,count,anch);
Try this.
static final Pattern PAT = Pattern.compile("(.)\\1*");
static String getCompressedString(String str) {
return PAT.matcher(str)
.replaceAll(m -> m.group(1)
+ (m.group().length() == 1 ? "" : m.group().length()));
}
Test cases:
#Test
public void testGetCompressedString() {
assertEquals("", getCompressedString(""));
assertEquals("a", getCompressedString("a"));
assertEquals("abc", getCompressedString("abc"));
assertEquals("abc3", getCompressedString("abccc"));
assertEquals("a3b2c2dsa", getCompressedString("aaabbccdsa"));
}
The regular expression "(.)\\1*" used here matches any sequence of identical characters. .replaceAll() takes a lambda expression as an argument, evaluates the lambda expression each time the pattern matches, and replaces the original string with the result.
The lambda expression is passed a Matcher object containing the results of the match. Here we are receiving this object in the variable m. m.group() returns the entire matched substring, m.group(1) returns its first character.
If the input string is "aaabbccdsa", it will be processed as follows.
m.group(1) m.group() returned by lambda
a aaa a3
b bb b2
c cc c2
d d d
s s s
a a a

I want the string pattern aabbcc to be displayed as 2a2b2c

I have somehow got the output with the help of some browsing. But I couldn't understand the logic behind the code. Is there any simple way to achieve this?
public class LetterCount {
public static void main(String[] args)
{
String str = "aabbcccddd";
int[] counts = new int[(int) Character.MAX_VALUE];
// If you are certain you will only have ASCII characters, I would use `new int[256]` instead
for (int i = 0; i < str.length(); i++) {
char charAt = str.charAt(i);
counts[(int) charAt]++;
}
for (int i = 0; i < counts.length; i++) {
if (counts[i] > 0)
//System.out.println("Number of " + (char) i + ": " + counts[i]);
System.out.print(""+ counts[i] + (char) i + "");
}
}
}
There are 3 conditions which need to be taken care of:
if (s.charAt(x) != s.charAt(x + 1) && count == 1) ⇒ print the counter and character;
if (s.charAt(x) == s.charAt(x + 1)) ⇒ increase the counter;
if (s.charAt(x) != s.charAt(x + 1) && count >= 2) ⇒ reset to counter 1.
{
int count= 1;
int x;
for (x = 0; x < s.length() - 1; x++) {
if (s.charAt(x) != s.charAt(x + 1) && count == 1) {
System.out.print(s.charAt(x));
System.out.print(count);
}
else if (s.charAt(x)== s.charAt(x + 1)) {
count++;
}
else if (s.charAt(x) != s.charAt(x + 1) && count >= 2) {
System.out.print(s.charAt(x));
System.out.print(count);
count = 1;
}
}
System.out.print(s.charAt(x));
System.out.println(count);
}
The code is really simple.It uses the ASCII value of a character to index into the array that stores the frequency of each character.
The output is simply got by iterating over that array and which character has frequency greater than 1, print it accordingly as you want in the output that is frequency followed by character.
If the input string has same characters consecutive then the solution can be using space of O(1)
For example in your string aabbcc, the same characters are consecutive , so we can take advantage of this fact and count the character frequency and print it at the same time.
for (int i = 0; i < str.length(); i++)
{
int freq = 1;
while((i+1)<str.length()&&str.charAt(i) == str.charAt(i+1))
{++freq;++i}
System.out.print(freq+str.charAt(i));
}
You are trying to keep count of the number of times each character is found. An array is referenced by an index. For example, the ASCII code for the lowercase letter a is the integer 97. Thus the count of the number of times the letter a is seen is in counts[97]. After every element in the counts array has been set, you print out how many have been found.
This should help you understand the basic idea behind how to approach the string compression problem
import java.util.*;
public class LetterCount {
public static void main(String[] args) {
//your input string
String str = "aabbcccddd";
//split your input into characters
String chars[] = str.split("");
//maintain a map to store unique character and its frequency
Map<String, Integer> compressMap = new LinkedHashMap<String, Integer>();
//read every letter in input string
for(String s: chars) {
//java.lang.String.split(String) method includes empty string in your
//split array, so you need to ignore that
if("".equals(s))
continue;
//obtain the previous occurances of the character
Integer count = compressMap.get(s);
//if the character was previously encountered, increment its count
if(count != null)
compressMap.put(s, ++count);
else//otherwise store it as first occurance
compressMap.put(s, 1);
}
//Create a StringBuffer object, to append your input
//StringBuffer is thread safe, so I prefer using it
//you could use StringBuilder if you don't expect your code to run
//in a multithreaded environment
StringBuffer output = new StringBuffer("");
//iterate over every entry in map
for (Map.Entry<String, Integer> entry : compressMap.entrySet()) {
//append the results to output
output.append(entry.getValue()).append(entry.getKey());
}
//print the output on console
System.out.println(output);
}
}
class Solution {
public String toFormat(String input) {
char inChar[] = input.toCharArray();
String output = "";
int i;
for(i=0;i<input.length();i++) {
int count = 1;
while(i+1<input.length() && inChar[i] == inChar[i+1]) {
count+=1;
i+=1;
}
output+=inChar[i]+String.valueOf(count);
}
return output;
}
public static void main(String[] args) {
Solution sol = new Solution();
String input = "aaabbbbcc";
System.out.println("Formatted String is: " + sol.toFormat(input));
}
}
def encode(Test_string):
count = 0
Result = ""
for i in range(len(Test_string)):
if (i+1) < len(Test_string) and (Test_string[i] == Test_string[i+1]):
count += 1
else:
Result += str((count+1))+Test_string[i]
count = 0
return Result
print(encode("ABBBBCCCCCCCCAB"))
If you want to get the correct count considering the string is not in alphabetical order. Sort the string
public class SquareStrings {
public static void main(String[] args) {
SquareStrings squareStrings = new SquareStrings();
String str = "abbccddddbd";
System.out.println(squareStrings.manipulate(str));
}
private String manipulate(String str1) {
//convert to charArray
char[] charArray = str1.toCharArray();
Arrays.sort(charArray);
String str = new String(charArray);
StringBuilder stbuBuilder = new StringBuilder("");
int length = str.length();
String temp = "";
if (length > 1) {
for (int i = 0; i < length; i++) {
int freq = 1;
while (((i + 1) < length) && (str.charAt(i) == str.charAt(i + 1))) {
++freq;
temp = str.charAt(i) + "" + freq;
++i;
}
stbuBuilder.append(temp);
}
} else {
return str + "" + 1;
}
return stbuBuilder.toString();
}
}
Kotlin:
fun compressString(input: String): String {
if (input.isEmpty()){
return ""
}
var result = ""
var count = 1
var char1 = input[0]
for (i in 1 until input.length) {
val char2 = input[i]
if (char1 == char2) {
count++
} else {
if (count != 1) {
result += "$count$char1"
count = 1
} else {
result += "$char1"
}
char1 = char2
}
}
result += if (count != 1) {
"$count$char1"
} else {
"$char1"
}
return result
}

Java String ReplaceFirst

I am reading in a string
Is Mississippi a State where there are many systems.
I would like to replace the 1st "s" or "S" in each word with "t" or "T" (i.e keeping the same case)...so that the output is:
It Mitsissippi a Ttate where there are many tystems.
I have tried
s= s.replaceFirst("(?i)S", "t"); [which of course didn't work]
and have experimented trying to split the string using a
string [] .split(Pattern.quote("\\s")) then trying to figure out how to replaceFirst() each element of the array and then return the values back to a string [but couldn't figure out the right way of doing it].
I thought \\G might help to restart at the next word but have gotten no where. Any help using these 3 methods is appreciated.
One option would be to split the string into words, and then use String.replaceFirst() on each word to replace the first occurrence of s with t (or any other letter you want):
Update:
I refactored my solution to find the first occurrence of any s (upper or lower case), and to apply the appropriate conversion on it.
String input = "Is Mississippi a State where there are many systems.";
String[] parts = input.split(" ");
StringBuilder sb = new StringBuilder("");
for (int i=0; i < parts.length; ++i) {
if (i > 0) {
sb.append(" ");
}
int index = parts[i].toLowerCase().indexOf('s');
if (index >= 0 && parts[i].charAt(index) == 's') {
sb.append(parts[i].replaceFirst("s", "t"));
}
else {
sb.append(parts[i].replaceFirst("S", "T"));
}
}
System.out.println(sb.toString());
Output:
It Mitsissippi a Ttate where there are many tystems.
Approach-1: Without using replace and split method for better performance.
String str = "Is Mississippi a State where there are many systems.";
System.out.println(str);
char[] cArray = str.toCharArray();
boolean isFirstS = true;
for (int i = 0; i < cArray.length; i++) {
if ((cArray[i] == 's' || cArray[i] == 'S') && isFirstS) {
cArray[i] = (cArray[i] == 's' ? 't' : 'T');
isFirstS = false;
} else if (Character.isWhitespace(cArray[i])) {
isFirstS = true;
}
}
str = new String(cArray);
System.out.println(str);
EDIT: Approach2: As you need to use replaceFirst method and you dont want to use StringBuilder here is an option for you:
String input = "Is Mississippi a State where there are many Systems.";
String[] parts = input.split(" ");
String output = "";
for (int i = 0; i < parts.length; ++i) {
int smallSIndx = parts[i].indexOf("s");
int capSIndx = parts[i].indexOf("S");
if (smallSIndx != -1 && (capSIndx == -1 || smallSIndx < capSIndx))
output += parts[i].replaceFirst("s", "t") + " ";
else
output += parts[i].replaceFirst("S", "T") + " ";
}
System.out.println(output); //It Mitsissippi a Ttate where there are many Tystems.
Note: I prefer approach 1 because it has no overhead for the method replaceFisrt and split , String append or concat
Use below amendment to Tim Biegeleisen's answer (before editing his post)
String input = "Is Mississippi a State where there are many systems.";
String[] parts = input.split(" ");
StringBuilder sb = new StringBuilder("");
for (String part : parts) {
sb.append(part.replaceFirst("s", "t").replaceFirst("S", "T"));
sb.append(" ");
}
System.out.println(sb.toString());
Edit - You can use concat()
String input = "Is Mississippi a State where there are many systems.";
String[] parts = input.split(" ");
String output = "";
for (String part : parts) {
output = output.concat(part.replaceFirst("s", "t").replaceFirst("S", "T") + " ");
}
System.out.println(output);
Update
String input = "Is Mississippi a State where there are many Systems.";
String[] parts = input.split(" ");
//StringBuilder sb = new StringBuilder("");
String output = "";
for (String part : parts) {
output = output.concat(part.replaceFirst("s", "t") + " ");
}
String[] parts2 = output.split(" ");
output = "";
for (String part : parts2) {
output = output.concat(part.replaceFirst("S", "T") + " ");
}
System.out.println(output);
I've created a method that -
is general purpose,
doesn't use replace or split, and
only uses one loop.
The following is my code snippet:
public static String replaceFirstOccurance(String sentence, char toChange, char changeWith) {
StringBuilder temp = new StringBuilder();
boolean changed = false;
for (int i = 0; i < sentence.length(); i++) {
if (!changed) {
if (sentence.charAt(i) == toChange) {
temp.append(changeWith);
changed = true;
} else if (sentence.charAt(i) == Character.toUpperCase(toChange)) {
temp.append(Character.toUpperCase(changeWith));
changed = true;
} else {
temp.append(sentence.charAt(i));
}
} else {
if (sentence.charAt(i) == ' ') {
changed = false;
}
temp.append(sentence.charAt(i));
}
}
return temp.toString();
}
My method would be less dependent on those string methods you've mentioned.
String phrase;
String [] parts = phrase.split(" ");
for (int i = 0; i < parts.length; i++ ) {
for (int j = 0; j < parts[i].length(); j++) {
if (parts[i].charAt(j) == 's') {
parts[i] = "t" + parts[i].substring(1);
break;
} else if (parts[i].charAt(0) == 'S') {
parts[i] = "T" + parts[i].substring(1);
break;
}
}
}
String modifiedPhrase = "";
for (int i = 0; i < parts.length; i++ ) {
modifiedPhrase += parts[i] + " ";
}
There is also a nice, compact, stream-based solution for that:
String result = Stream.of(s.split(" "))
.map(t -> t.replaceFirst("s", "t"))
.map(t -> t.replaceFirst("S", "T"))
.collect(Collectors.joining(" "));
String ss = "Is Mississippi a State where there are many systems.";
String out = "";//replaced string
for (String s : ss.split(" ")) {
int index = s.toUpperCase().indexOf('S');
out += (s.replaceFirst("[s,S]", index!= -1 && s.charAt(index) == 'S'
? "T" : "t")) + " ";
}
System.out.println(out);

How do I find what's inbetween " " in an inputted string? [duplicate]

I'd like to retrieve whatever is in quotes that someone enters as a string, i'm assuming it's substring that I need but i'm not sure how.
When the user inputs a string mixed with words and numbers all separated by one space:
hey 110 say "I am not very good at Java" but " I can fish pretty well"
Then I want to be able to take the "I am not very good at Java" and the "I can fish pretty well" and print out what's inside the quotes so there can be multiple quotes in the string.
right now I have if( userInput=='"') then I do something with substring but i'm not sure what.
I can't use split, trim, tokenizer, regex or anything that would make this really easy unfortunatley.
it's all in this method where I try to identify if something in the string is a word, number or a quote:
public void set(String userInput)// method set returns void
{
num=0;// reset each variable so new input can be passed
String empty="";
String wordBuilder="";
userInput+=" ";
for(int index=0; index<userInput.length(); index++)// goes through each character in string
{
if(Character.isDigit(userInput.charAt(index)))// checks if character in the string is a digit
{
empty+=userInput.charAt(index);
}
else
{
if (Character.isLetter(userInput.charAt(index)))
{
wordBuilder+=userInput.charAt(index);
}
else
{
if(userInput.charAt(index)=='"')
{
String quote=(userInput.substring(index,);
}
}
//if it is then parse that character into an integer and assign it to num
num=Integer.parseInt(empty);
word=wordBuilder;
empty="";
wordBuilder="";
}
}
}
}
Thanks!
Try the next:
public static void main(String[] args) {
String input = "\"123\" hey 110 say \"I am not very good at Java\" but \" I can fish pretty well\"";
int indexQuote = -1;
boolean number = true;
String data = "";
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (Character.isWhitespace(ch)) {
if (data.length() > 0 && indexQuote == -1) {
if (number) {
System.out.println("It's a number: " + data);
} else {
System.out.println("It's a word: " + data);
}
// reset vars
number = true;
data = "";
} else if (indexQuote != -1) {
data += ch;
}
} else if (ch == '"') {
if (indexQuote == -1) {
number = false;
indexQuote = i;
} else {
System.out.println("It's a quote: " + data);
// reset vars
number = true;
data = "";
indexQuote = -1;
}
} else {
if (!Character.isDigit(ch)) {
number = false;
}
data += ch;
if (data.length() > 0 && i == input.length() - 1) {
if (number) {
System.out.println("It's a number: " + data);
} else {
System.out.println("It's a word: " + data);
}
}
}
}
}
Output:
It's a word: hey
It's a number: 110
It's a word: say
It's a quote: I am not very good at Java
It's a word: but
It's a quote: I can fish pretty well
I'm not sure if this quite what you are looking for, but it will strip down the quoted parts in steps...
String quote = "I say: \"I have something to say, \"It's better to burn out then fade away\"\" outloud...";
if (quote.contains("\"")) {
while (quote.contains("\"")) {
int startIndex = quote.indexOf("\"");
int endIndex = quote.lastIndexOf("\"");
quote = quote.substring(startIndex + 1, endIndex);
System.out.println(quote);
}
}
Which outputs...
I have something to say, "It's better to burn out then fade away"
It's better to burn out then fade away
Updated
I don't know if this is cheating or not...
String quote = "I say: \"I have something to say, \"It's better to burn out then fade away\"\" outloud...\"Just in case you don't believe me\"";
String[] split = quote.split("\"");
for (String value : split) {
System.out.println(value);
}
Which outputs...
I say:
I have something to say,
It's better to burn out then fade away
outloud...
Just in case you don't believe me
Updated
Okay, fake String#split
StringBuilder sb = new StringBuilder(quote.length());
for (int index = 0; index < quote.length(); index++) {
if (quote.charAt(index) == '"') {
System.out.println(sb);
sb.delete(0, sb.length());
} else {
sb.append(quote.charAt(index));
}
}
Updated
Okay, this is basically fake split with options...
String quote = "blah blah 123 \"hello\" 234 \"world\"";
boolean quoteOpen = false;
StringBuilder sb = new StringBuilder(quote.length());
for (int index = 0; index < quote.length(); index++) {
if (quote.charAt(index) == '"') {
if (quoteOpen) {
System.out.println("Quote: [" + sb.toString() + "]");
quoteOpen = false;
sb.delete(0, sb.length());
} else {
System.out.println("Text: [" + sb.toString() + "]");
sb.delete(0, sb.length());
quoteOpen = true;
}
} else {
sb.append(quote.charAt(index));
}
}
if (sb.length() > 0) {
if (quoteOpen) {
System.out.println("Quote: [" + sb.toString() + "]");
} else {
System.out.println("Text: [" + sb.toString() + "]");
}
}
Which generates...
Text: [blah blah 123 ]
Quote: [hello]
Text: [ 234 ]
Quote: [world]
Know, I don't know how you are storing the results. I would be tempted to create some basic classes which were capable of storing the String results and add them to a List so I could maintain the order and maybe use a flag of some kind to determine what type they are...
Iterate over the string and use a temporary int variable to store when the quoted string started. When you see that it ends, you can extract that substring and do what you want with it.
Use StringUtils.subStringBetween
public class MyTestSecond {
public static void main(String...args){
String a = "hey 110 say \"I am not very good at Java\"";
// Method 1
if(a.contains("\""))
System.out.println(a.substring(a.indexOf("\""),a.lastIndexOf("\"")+1));
//Method 2
String[] array = a.split(" ");
for(int i=0;i<array.length;i++){
if(array[i].startsWith("\""))
System.out.println(a.substring(a.indexOf("\""),a.lastIndexOf("\"")+1));
}
}
}
public String getNextQuote(int index, String sentence){
return sentence.substring(sentence.indexOf("\"", index + 1), sentence.indexOf("\"", index + 2));
}
usage: call the method with an index as parameter. This index resembles the index of the last " that you've encountered.
Afterwards, it will return everything between the next two quotes.

Checking if a string matches all characters but one of another string

I have a list of strings and with each string I want to check it's characters against every other string to see if all it's characters are identical except for one.
For instance a check that would return true would be checking
rock against lock
clock and flock have one character that is different, no more no less.
rock against dent will obviously return false.
I have been thinking about first looping through the list and then having a secondary loop within that one to check the first string against the second.
And then using split(""); to create two arrays containing the characters of each string and then checking the array elements against each other (i.e. comparing each string with the same position in the other array 1-1 2-2 etc...) and so long as only one character comparison fails then the check for those two strings is true.
Anyway I have a lot of strings (4029) and considering what I am thinking of implementing at the moment would contain 3 loops each within the other that would result in a cubic loop(?) which would take a long long time with that many elements wouldn't it?
Is there an easier way to do this? Or will this method actually work okay? Or -hopefully not- but is there some sort of potential logical flaw in the solution I have proposed?
Thanks a lot!
Why not do it the naive way?
bool matchesAlmost(String str1, String str2) {
if (str1.length != str2.length)
return false;
int same = 0;
for (int i = 0; i < str1.length; ++i) {
if (str1.charAt(i) == str2.charAt(i))
same++;
}
return same == str1.length - 1;
}
Now you can just use a quadratic algorithm to check every string against every other.
Assuming the length of two strings are equal
String str1 = "rock";
String str2 = "lick";
if( str1.length() != str2.length() )
System.out.println( "failed");
else{
if( str2.contains( str1.substring( 0, str1.length()-1)) || str2.contains( str1.substring(1, str1.length() )) ){
System.out.println( "Success ");
}
else{
System.out.println( "Failed");
}
}
Not sure if this is the best approach but this one works even when two strings are not of same length. For example : cat & cattp They differ by one character p and t is repeated. Looks like O(n) time solution using additional space for hashmap & character arrays.
/**
* Returns true if two strings differ by one character
* #param s1 input string1
* #param s2 input string2
* #return true if strings differ by one character
*/
boolean checkIfTwoStringDifferByOne(String s1, String s2) {
char[] c1, c2;
if(s1.length() < s2.length()){
c1 = s1.toCharArray();
c2 = s2.toCharArray();
}else{
c1 = s2.toCharArray();
c2 = s1.toCharArray();
}
HashSet<Character> hs = new HashSet<Character>();
for (int i = 0; i < c1.length; i++) {
hs.add(c1[i]);
}
int count = 0;
for (int j = 0; j < c2.length; j++) {
if (! hs.contains(c2[j])) {
count = count +1;
}
}
if(count == 1)
return true;
return false;
}
Assuming that all the strings have the same length, I think this would help:
public boolean differByOne(String source, String destination)
{
int difference = 0;
for(int i=0;i<source.length();i++)
{
if(source.charAt(i)!=destination.charAt(i))
{
difference++;
if(difference>1)
{
return false;
}
}
}
return difference == 1;
}
Best way is to concatenate strings together one forward and other one in reverse order. Then check in single loop for both ends matching chars and also start from middle towards ends matching char. If more than 2 chars mismatch break.
If one mismatch stop and wait for the next one to complete if it reaches the same position then it matches otherwise just return false.
public static void main(String[] args) {
New1 x = new New1();
x.setFunc();
}
static void setFunc() {
Set s = new HashSet < Character > ();
String input = " aecd";
String input2 = "abcd";
String input3 = new StringBuilder(input2).reverse().toString();
String input4 = input.concat(input3);
int length = input4.length();
System.out.println(input4);
int flag = 0;
for (int i = 1, j = length - 1; j > i - 1; i++, j--) {
if (input4.charAt(i) != input4.charAt(j)) {
System.out.println(input4.charAt(i) + " doesnt match with " + input4.charAt(j));
if (input4.charAt(i + 1) != input4.charAt(j)) {
System.out.println(input4.charAt(i + 1) + " doesnt match with " + input4.charAt(j));
flag = 1;
continue;
} else if (input4.charAt(i) != input4.charAt(j - 1)) {
System.out.println(input4.charAt(i) + " doesnt match with " + input4.charAt(j - 1));
flag = 1;
break;
} else if (input4.charAt(i + 1) != input4.charAt(j - 1) && i + 1 <= j - 1) {
System.out.println(input4.charAt(i + 1) + " doesnt match with xxx " + input4.charAt(j - 1));
flag = 1;
break;
}
} else {
continue;
}
}
if (flag == 0) {
System.out.println("Strings differ by one place");
} else {
System.out.println("Strings does not match");
}
}

Categories

Resources