Finding the first letter in a String - java

I have a String
String s="#$% AbcD89";
And I'm trying to get the first letter of that String regardless of if it's capitalized or not. However, I do not know how many characters are before that first letter. I have tried using
int index=0;
outerloop:
for(int i=0; i<s.length;i++) {
if(Character.isLetter(s.chartAt(i)) { //Tried with isAlphabetic as well
index=i;
break outerloop;
}
}
But these return what seems to be a random character. Basically, that doesn't return the first letter
Note I cannot use Pattern and Matcher classes

Try it like this. Note that 0 is a legitimate location as an index so initialize your index to -1 and test before using.
String s = "#$% AbcD89";
int index = -1;
for (int i = 0; i < s.length(); i++) {
if (Character.isLetter(s.charAt(i))) {
index = i;
break;
}
}
if (index < 0) {
System.out.println("No letter found!");
} else {
System.out.println("First letter is : " + s.charAt(index));
}
prints
First letter is : A

Related

Check for multiple occurrence of certain character in string

Edit: To those who downvote me, this question is difference from the duplicate question which you guy linked. The other question is about returning the indexes. However, for my case, I do not need the index. I just want to check whether there is duplicate.
This is my code:
String word = "ABCDE<br>XYZABC";
String[] keywords = word.split("<br>");
for (int index = 0; index < keywords.length; index++) {
if (keywords[index].toLowerCase().contains(word.toLowerCase())) {
if (index != (keywords.length - 1)) {
endText = keywords[index];
definition.setText(endText);
}
}
My problem is, if the keywords is "ABC", then the string endText will only show "ABCDE". However, "XYZABC" contains "ABC" as well. How to check if the string has multiple occurrence? I would like to make the definition textview become definition.setText(endText + "More"); if there is multiple occurrence.
I tried this. The code is working, but it is making my app very slow. I guess the reason is because I got the String word through textwatcher.
String[] keywords = word.split("<br>");
for (int index = 0; index < keywords.length; index++) {
if (keywords[index].toLowerCase().contains(word.toLowerCase())) {
if (index != (keywords.length - 1)) {
int i = 0;
Pattern p = Pattern.compile(search.toLowerCase());
Matcher m = p.matcher( word.toLowerCase() );
while (m.find()) {
i++;
}
if (i > 1) {
endText = keywords[index];
definition.setText(endText + " More");
} else {
endText = keywords[index];
definition.setText(endText);
}
}
}
}
Is there any faster way?
It's a little hard for me to understand your question, but it sounds like:
You have some string (e.g. "ABCDE<br>XYZABC"). You also have some target text (e.g. "ABC"). You want to split that string on a delimiter (e.g. "<br>", and then:
If exactly one substring contains the target, display that substring.
If more than one substring contains the target, display the last substring that contains it plus the suffix "More"
In your posted code, the performance is really slow because of the Pattern.compile() call. Re-compiling the Pattern on every loop iteration is very costly. Luckily, there's no need for regular expressions here, so you can avoid that problem entirely.
String search = "ABC".toLowerCase();
String word = "ABCDE<br>XYZABC";
String[] keywords = word.split("<br>");
int count = 0;
for (String keyword : keywords) {
if (keyword.toLowerCase().contains(search)) {
++count;
endText = keyword;
}
}
if (count > 1) {
definition.setText(endText + " More");
}
else if (count == 1) {
definition.setText(endText);
}
You are doing it correctly but you are doing unnecessary check which is if (index != (keywords.length - 1)). This will ignore if there is match in the last keywords array element. Not sure is that a part of your requirement.
To enhance performance when you found the match in second place break the loop. You don't need to check anymore.
public static void main(String[] args) {
String word = "ABCDE<br>XYZABC";
String pattern = "ABC";
String[] keywords = word.split("<br>");
String endText = "";
int count = 0;
for (int index = 0; index < keywords.length; index++) {
if (keywords[index].toLowerCase().contains(pattern.toLowerCase())) {
//If you come into this part mean found a match.
if(count == 1) {
// When you found the second match it will break to loop. No need to check anymore
// keep the first found String and append the more part to it
endText += " more";
break;
}
endText = keywords[index];
count++;
}
}
System.out.println(endText);
}
This will print ABCDE more
Hi You have to use your condition statement like this
if (word.toLowerCase().contains(keywords[index].toLowerCase()))
You can use this:
String word = "ABCDE<br>XYZABC";
String[] keywords = word.split("<br>");
for (int i = 0; i < keywords.length - 1; i++) {
int c = 0;
Pattern p = Pattern.compile(keywords[i].toLowerCase());
Matcher m = p.matcher(word.toLowerCase());
while (m.find()) {
c++;
}
if (c > 1) {
definition.setText(keywords[i] + " More");
} else {
definition.setText(keywords[i]);
}
}
But like what I mentioned in comment, there is no double occurrence in word "ABCDE<br>XYZABC" when you want to split it by <br>.
But if you use the word "ABCDE<br>XYZABCDE" there is two occurrence of word "ABCDE"
void test() {
String word = "ABCDE<br>XYZABC";
String sequence = "ABC";
if(word.replaceFirst(sequence,"{---}").contains(sequence)){
int startIndex = word.indexOf(sequence);
int endIndex = word.indexOf("<br>");
Log.v("test",word.substring(startIndex,endIndex)+" More");
}
else{
//your code
}
}
Try this

A simple encryption idea from a String ArrayList in Java

I have a given String ArrayList. Using the elements in the ArrayList, I wanted to create a string. The string is obtained by displaying the characters in a column, inserting a space, and then displaying the next column and inserting a space, and so on. For example, the array list as follows :
[stac, kove, rflo, w]
My string should be the first letter of the first element and first letter of the second element (finish the array elements) and space, then second letter of the first element and second letter of the second element and so on. The result should be:
skrw tof avl ceo
Here is the closest code that I had:
public static String display(ArrayList<String> words){
String s = "";
for(int i=0; i<words.size(); i++){
for(int j=0; j<words.get(i).length(); j++){
s += words.get(i).charAt(j) + " ";
}
}
return s;
}
Any help will be appreciated.
This is the function match the output that you want:
public static String display(ArrayList<String> words) {
String s = "";
int index = 0;
boolean hit = false;
while (!hit) {
for (int i = 0; i < words.size(); i++) {
String w = words.get(i);
if (w.length() > index) {
s += w.charAt(index);
hit = true;
}
}
if (hit) {
hit = false;
index++;
s += " ";
} else {
hit = true;
}
}
return s.trim();
}

Exception in thread "main" java.lang.StringIndexOutOfBoundsException

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 7
at java.lang.String.charAt(Unknown Source)
at DNAmatch.findFirstMatchingPosition(DNAmatch.java:100)
at DNAmatch.run(DNAmatch.java:82)
at acm.program.Program.runHook(Program.java:1568)
at acm.program.Program.startRun(Program.java:1557)
at acm.program.Program.start(Program.java:808)
at acm.program.Program.start(Program.java:1279)
at acm.program.Program.main(Program.java:1360)
I got this weird error and I don't know what is causing it. I googled for a solution to my problem but nothing helped me solve it.
If you try as inputs for chain1 atcg and for chain2 tagaagtc, it works fine
but for inputs chain1 atcg and chain2 tagaagct then i got this error.
If anyone could help i'd appreciate it.
=================================================
import acm.program.*;
public class DNAmatch extends Program
{
public void run()
{
//The chains must only contain the characters A,T,C or G so we check the string for any irregularities.
String current, chain2; Boolean flag=true; int errorCount;
String chain1 = readLine("Please type in the first chain of DNA code: ");
for (int i=0; i<chain1.length(); i++)
{
current = chain1.charAt(i) +"";
if (!((current.equalsIgnoreCase("a"))||(current.equalsIgnoreCase("t"))||
(current.equalsIgnoreCase("c"))||(current.equalsIgnoreCase("g"))))
{
flag=false; break;
}
}
while (flag==false)
{
errorCount=0;
println("The DNA code you insert must only contain the characters A, T, C and G");
chain1 = readLine("Please type again in the first chain of DNA code: ");
for (int i=0; i<chain1.length(); i++)
{
current=chain1.charAt(i) +"";
if (!((current.equalsIgnoreCase("a"))||(current.equalsIgnoreCase("t"))||
(current.equalsIgnoreCase("c"))||(current.equalsIgnoreCase("g"))))
{
errorCount =1; break;
}
}
if (errorCount==0)
{
flag=true; break;
}
}
chain2 = readLine("Please type in the second chain of DNA code: ");
flag=true;
for (int i=0; i<chain2.length(); i++)
{
current = chain2.charAt(i) +"";
if (!((current.equalsIgnoreCase("a"))||(current.equalsIgnoreCase("t"))||
(current.equalsIgnoreCase("c"))||(current.equalsIgnoreCase("g")))&&(chain1.length()>chain2.length()))
{
flag= false; break;
}
}
while ((flag==false)&&(chain1.length()>chain2.length()))
{
errorCount=0;
if (chain1.length()>chain2.length())
println("The second DNA chain must be longer or equal to the first one at the most!");
else
println("The DNA code you insert must only contain the characters A, T, C and G");
chain2 = readLine("Please type again the second chain of DNA code: ");
for (int i=0; i<chain2.length(); i++)
{
current = chain2.charAt(i) +"";
if (!((current.equalsIgnoreCase("a"))||(current.equalsIgnoreCase("t"))||
(current.equalsIgnoreCase("c"))||(current.equalsIgnoreCase("g")))&&(chain1.length()>chain2.length()))
{
errorCount =1; break;
}
}
if (errorCount==0)
{
flag=true;
}
}
int match=findFirstMatchingPosition(chain1,chain2);
if (match==-1)
println("Not match found! "+ match);
else
println("Match has been found at point "+ match+ "!");
}
public int findFirstMatchingPosition(String shortDNA, String longDNA)
{
String currentCharShort=""; String currentCharLong="";
int match=0; int ans=-1; int a;
for (int i=0; i < longDNA.length(); i++)
{
a = i;
match = 0;
for (int j=0; j < shortDNA.length(); j++)
{
currentCharLong=longDNA.charAt(a)+ "";
currentCharShort=shortDNA.charAt(j)+ "";
if ( (currentCharShort.equalsIgnoreCase("a") && currentCharLong.equalsIgnoreCase("t"))||
(currentCharShort.equalsIgnoreCase("t") && currentCharLong.equalsIgnoreCase("a"))||
(currentCharShort.equalsIgnoreCase("c") && currentCharLong.equalsIgnoreCase("g"))||
(currentCharShort.equalsIgnoreCase("g") && currentCharLong.equalsIgnoreCase("c")) )
{
match +=1;
a +=1;
}
else break;
}
if (match == shortDNA.length())
{
ans=i;
break;
}
}
return ans;
}
}
if ( (currentCharShort.equalsIgnoreCase("a") && currentCharLong.equalsIgnoreCase("t"))||
(currentCharShort.equalsIgnoreCase("t") && currentCharLong.equalsIgnoreCase("a"))||
(currentCharShort.equalsIgnoreCase("c") && currentCharLong.equalsIgnoreCase("g"))||
(currentCharShort.equalsIgnoreCase("g") && currentCharLong.equalsIgnoreCase("c")) )
{
match +=1;
a +=1;
}
This is where your problem is, since you nested the loop, 'a' has the opportunity to increment greater than the total length of longDNA.
When you enter this for loop
for (int j=0; j < shortDNA.length(); j++)
{
currentCharLong=longDNA.charAt(a)+ "";
currentCharShort=shortDNA.charAt(j)+ "";
if ( (currentCharShort.equalsIgnoreCase("a") && currentCharLong.equalsIgnoreCase("t"))||
(currentCharShort.equalsIgnoreCase("t") && currentCharLong.equalsIgnoreCase("a"))||
(currentCharShort.equalsIgnoreCase("c") && currentCharLong.equalsIgnoreCase("g"))||
(currentCharShort.equalsIgnoreCase("g") && currentCharLong.equalsIgnoreCase("c")) )
{
match +=1;
a +=1;
}
else break;
}
with "a" that is the index of your last character in longDNA (say 5 if longDNA has six characters), when you enter the if branch and put a+=1 you now have an index that is greater than longDNA size. So when you iterate again and search for charAt(a) the exception will be thrown. This could also happen with lesser "a" if you execute the a+=1 statement different times in the internal for loop.

Counting sentences, only sentences ending with punctuation + 2 spaces

I'm trying to figure out how to make a sentence counter, which I have, but the thing is, I need it to count a sentence ONLY when two spaces come after the period/question mark/etc.
For example, with the code I have, if you enter the string "hello, my name is ryan..." it returns the count of 3 sentences. I need it to only count one sentence.
This program needs to count words also. I count the words by taking the amount of spaces - 1. This is where my problem lies, I either mess up the word count or the sentence count.
Here is the method for the word count:
public static int countWords(String str){
if(str == null || str.isEmpty())
return 0;
int count = 0;
for(int i = 0; i < str.length(); i++){
if(str.charAt(i) != ' '){
count++;
while(str.charAt(i) != ' ' && i < str.length()-1){
i++;
}
}
}
return count;
}
And here is the method for counting sentences:
public static int sentenceCount(String str) {
String SENTENCE_ENDERS = ".?!";
int sentenceCount=0;
int lastIndex=0;
for(int i=0;i < str.length(); i++){
for(int j=0;j < SENTENCE_ENDERS.length(); j++){
if(str.charAt(i) == SENTENCE_ENDERS.charAt(j)){
if(lastIndex != i-1){
sentenceCount++;
}
lastIndex = i;
}
}
}
return sentenceCount;
}
I actually got it, using regex, was super simple also.
public static int sentenceCount(String str) {
String regex = "[?|!|.]+[ ]+[ ]";
Pattern p = Pattern.compile(regex);
int count = 0;
Matcher m = p.matcher(str);
while (m.find()) {
count++;
}
if (count == 0){
return 1;
}
else {
return count + 1;
}
}
Works great, I added the if statement assuming user is inputting at least one sentence, and added one to the count assuming they won't put two spaces at the end of their last sentence.

What's wrong with my if-else statement?

I made this simple GUI program that counts the vowels and consonants of a particular sequence of characters. The counter is okay, but I'm having a problem with the if-else statement where I had to display a message when that character is neither a vowel nor consonant... Here's the code:
//I initialized these variables:
public static int vowels = 0, consonants = 0, charac = 0;
public static String outputStr;
public static String conso = "bcdfghjklmnpqrstvwxyz";
public static String vow = "aeiou";
//Here's the code for my "count" button
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String userInput = jTextField1.getText();
userInput = userInput.toUpperCase();
conso = conso.toUpperCase();
vow = vow.toUpperCase();
String wordInput[] = userInput.split("");
vowels = 0;
consonants = 0;
charac = 0;
for(int i=0; i<wordInput.length; i++) {
for(int j=0; j<5; j++) {
char v = vow.charAt(j);
String VL = Character.toString(v);
if(VL.equals(wordInput[i])) {
vowels ++;
charac = 0;}
else {
charac += 1; }
}
for(int h=0; h<21; h++) {
char c = conso.charAt(h);
String CL = Character.toString(c);
if(CL.equals(wordInput[i])) {
consonants ++;
charac = 0; }
else {
charac += 1; }
}
}
String totalVow = Integer.toString(vowels);
String totalCons = Integer.toString(consonants);
jLabel5.setText(totalVow);
jLabel6.setText(totalCons);
//here's the if-else statement:
if (charac == 0) {
jLabel7.setText(" ");
}
else if (charac >= 1) {
jLabel7.setText("The sequence contains invalid characters.");
}
if (userInput.isEmpty()) {
jLabel7.setText("No input.");
}
}
Here's what it looks like:
I entered a "sequence" of characters that does not have any special characters or digits. But it still displays the message wherein it has other characters other than the vowels and consonants. Is there something wrong with the if-else statement? Thanks for the help :)
The problem is in the inner for loop. Every character is tested with each of 5 different vowels, so surely it will fail to match at least 4 of them, and charac will be incremented
for(int j=0; j<5; j++) {
char v = vow.charAt(j);
String VL = Character.toString(v);
if(VL.equals(wordInput[i])) {
vowels ++;
charac = 0;}
else {
charac += 1;
}
}
Instead, you can use the String.contains() method in place of the inner loop.
You put irrelevant code in your loop. Your loop should like:
for(int i=0; i<wordInput.length; i++) {
char ch=wordInput.charAt(i);
if(Character.isLetter(ch)){
if(isVowel(ch)){// make a method which return true if char is vowel.
vowel++;
}
else{
consonent++;
}
}
}
Your logic for counting invalid characters if wrong. What you do is: you increase the counter each time the character is not the character you just tested, that is, for each character in your input, the charac variable is increased 25 times! But then, the next time the character matches the currently tested vowel or consonant, you reset the charac variable to 0!
Instead of using two for loops to check for each of your vowels and consonants individually, you can use builtin String methods to check whether the current character is one of the vowels or consonants, e.g., indexOf. This way, the checks are reduced to a single if-statement each, making it much easier to have the "else" case for when it's neither a vowel nor a consonant.
for (int i = 0; i < userInput.length(); i++) {
char c = userInput.charAt(i);
if (vow.indexOf(c) != -1) {
vowels++;
} else if (conso.indexOf(c) != -1) {
consonants++;
} else {
charac++; // invalid character
}
}
Also, note that instead of splitting the string to an array of strings you can also use the charAt method.
You're adding to charac in both loops: one that looks up the consonants and the one that looks up the vowels. You'd want to use an if/else-if/else here, where only if a character is not a consonant or a vowel you add to charac.
Also, take a look Guava utilities. For instance, this is how you get all vowels and all consonants:
String vowels = "aeiou";
String consonants = "bcdfghjklmnpqrstvwxz";
String input = "mary had a little lamb";
String allVowels = CharMatcher.anyOf(vowels).retainFrom(input);
String allConsonants = CharMatcher.anyOf(consonants).retainFrom(input);

Categories

Resources