Is there a way to remove all non alphabet character from a String without regex?
I'm trying to check if the String is a palindrome
This is what i tried so far.
public static boolean isPalindrome( String text )
{
int textLength = text.length() - 1;
String reformattedText = text.trim().toLowerCase();
for( int i = 0; i <= textLength; i++ )
{
if( reformattedText.charAt( i ) != reformattedText.charAt( textLength - i ) )
{
return false;
}
}
return true;
}
But if the input is:
System.out.println( isPalindrome( "Are we not pure? No sir! Panama’s moody"
+ "Noriega brags. It is garbage! Irony dooms a man; a prisoner up to new era." ) );
It should be true.
I'm really having a hard time thinking of how to remove or ignore those non alphabet characters on the String.
I would do something like this:
public static String justAlphaChars(String text) {
StringBuilder builder = new StringBuilder();
for (char ch : text.toCharArray())
if (Character.isAlphabetic(ch))
builder.append(ch);
return builder.toString();
}
Just tested method above in your example bellow and worked. Returned true.
System.out.println( isPalindrome( justAlphaChars ( "Are we not pure? No sir! Panama’s moody"
+ "Noriega brags. It is garbage! Irony dooms a man; a prisoner up to new era." ) ) );
OOPS. Java, not Python.
You can still use list-like access in Java, just a bit more work.
char[] letters = text.toCharArray();
int nletters = 0;
for (int i=0; i<letters.length; ++i) {
if (Character.isLetter(letters[i])
letters[nletters++] = Character.toUpperCase(letters[i]);
}
// print out letters in array:
System.out.print("letters only: ");
for (int i=0; i<nletters; ++i) {
System.out.print(letters[i]);
}
System.out.println();
Now use the first nletters positions only in the letters array, since those positions will hold the lowercased letters from the input. An example that just displays the remaining characters is included above.
Now write a loop to compare letters[0] with letters[nletters-1], letters[1] with letters[nletters-2], and so on. If all pairs are equal, you have a palindrome.
String removeNonAlpha(final String word) {
final StringBuilder result = new StringBuilder();
for (final char ch : word.toCharArray()) {
final int ascii = ch;
if (((ascii >= 65) && (ascii <= 90)) || ((ascii >= 97) && (ascii <= 122))) {
result.append(ch);
}
}
return result.toString();
}
Explanation:
The method will retrieve a string containing only A-Z and a-z characters.
I am simply verifying the ascii code for the given char.
Please refer to the ASCII code table
Related
Ii am having trouble my below code I am building a project which requires the user to input "This is some \"really\" great. (Text)!?" which is then converted into THISISSOMEREALLYGREATTEXT and the value is passed into the next parameter. then in my Obify method I am attempting to add OB in front of every vowel AEIOUY but in my function it does not do this effectively, it prints out THISISSOMEREALLYGREATTEXT numerous times and with each new time it passes THISISSOMEREALLYGREATTEXT it adds in OB at the end when I need OB infront of every vowel instead of just at the end. please do show me where I am going wrong so I can continue to progress. once again thank you in advance and the code under review is below.
import java.util.*;
public class Main {
public static void main(String[] args) {
normalizeText();
obify("THISISSOMEREALLYGREATTEXT" );
}
// Part 1 Normalized Method to convert all letter to uppercase and removing all special characters and placing it into String codey.
public static String normalizeText (){
Scanner sc = new Scanner( System.in );
String normText;
System.out.println("Please input text to encrypt");
normText = sc.nextLine();
System.out.println(normText.replaceAll(" ","").replaceAll("[^a-zA-Z ]", "").toUpperCase());
return normText;
}
//This method will take in the Normalized text and insert a capital O and B in-front of every vowel and return the text
private static String obify (String input) {
String obifiledInput = input;
for (int i = 0; i < input.length(); i++) {
if (input.contains( Character.toString( input.charAt( i ) ) )) {
obifiledInput = obifiledInput + "OB" + Character.toString( input.charAt( i ) );
} else {
obifiledInput = obifiledInput + Character.toString( input.charAt( i ) );
}
System.out.println(obifiledInput);
}
return obifiledInput;
}
}
Looking at your obify function, I don't quite see where it is that you are checking if the Character is a vowel. What the following code:
if (input.contains( Character.toString( input.charAt( i ) ) ))
is doing is checking if input contains a character at a certain position in input. That doesn't quite solve your problem of checking if the letter is a vowel. Additionally, you are setting obifiledInput to input directly without first going through and adding the OB when required. To fix these problems, you can try my code below:
private static String obify (String input) {
String obifiledInput = "";
for (int i = 0; i < input.length(); i++) {
char temp = input.charAt(i);
if (char == 'A' || char == 'E' || char == 'I' || char == 'O' || char == 'U') {
obifiledInput += "OB" + temp;
} else {
obifiledInput += "" + temp;
}
}
return obifiledInput;
}
I think that you should find that this works. It checks if the character is a vowel, ["A", "E", "I", "O", "U"]. Then, it adds "OB" and the character to obifiledInput. Otherwise, it just adds the Character. Finally, it returns the String that has been "obified".
Just match input.charAt(i) with all the vowels it should do fine. Also there is a small mistake in your code, you have initialized oblifiedInput with input and then you are adding OB to that string. Even if your for loop was correct it still would have not resulted in the required output.
private static String obify (String input) {
String obifiledInput = "";
char c;
for (int i = 0; i < input.length(); i++) {
c=input.charAt(i);
if (c=='a' || c=='e' || c=='i' || c=='o' || c=='u') {
obifiledInput +="OB";
}
obifiledInput +=c;
}
System.out.println(obifiledInput);
return obifiledInput;
}
Wouldn't it be easier to use an array of char, pass said array into a for each structure, and then use the replaceAll(String regex, String replacement) method on your String?
Plus, there is the risk of having the 'O' of "OB" being considered as another vowel of the code; so 'O' will have to be the first vowel to be checked.
It would give something around the line of:
String obifiledInput = input;
ArrayList<Character> vowels = { 'O', 'A', 'E', 'I', 'U', 'Y' };
for (char curr_char : vowels) {
obifiledInput.remplaceAll( "[" + curr_char + "]", "OB" + curr_char)
System.out.println(obifiledInput);
}
return obifiledInput;
I am developing a method which takes ArrayList as an argument.
Then, the method makes some changes into the array and returns transformed arrayList.
The input array is going to be like that {A123, C123, 15B2} and I would like to get the following output {Aa123, Cc123, 15Bb2}.
That is to say, after any capital letter I need to add the same lowercase letter.
And there are any order and quantity of letters, e.g. it is also possible to get strings like those Hkjk124, hy71.
The method is shown below:
protected ArrayList<String> enrichValues(ArrayList<String> list) {
for (int i = 0; i < list.size(); i++) {
char[] charArray = list.get(i).toCharArray();
List<Character> listChars = new ArrayList<>();
for (char c : charArray) {
listChars.add(c);
}
for (int j = 0; j < listChars.size(); j++) {
if (listChars.get(j).charValue() == 'A') {
listChars.add(j + 1, 'a');
}
}
String newChar = "";
for (Character c : listChars)
newChar += c.toString();
list.set(i, newChar);
}
return list;
}
The main problem I have faced to is that I do not know how to check if a letter is uppercase.
I failed to apply something like:
if(Character.isLetter(c) && Character.isUpperCase(c)) {
listChars.add(j + 1, 'a');
}
Because of that I have to add lots of checks:
if (listChars.get(j).charValue() == 'B') {
listChars.add(j + 1, 'b');
}
if (listChars.get(j).charValue() == 'C') {
listChars.add(j + 1, 'c');
}
But it is a very bad approach. I would appreciate any help.
Here's a way of doing it that works like a charm :
public static ArrayList<String> enrichValues(ArrayList<String> values){
ArrayList<String> array = new ArrayList<String>();
for (String str : values){ //For each string
StringBuilder copy = new StringBuilder();
for (char c : str.toCharArray()) {//For each char
copy.append(c);
if(Character.isLetter(c) && Character.isUpperCase(c)){
copy.append(Character.toLowerCase(c));
}
}
array.add(copy.toString());
}
return array;
}
Example :
public static void main(String[] args) {
String a = "A123";
String b = "C123";
String c = "15B2";
String d = " Hkjk124";
String e = "hy71";
String g = "AbCdE645 DeeeFFD";
ArrayList<String> values = new ArrayList<String>();
values.add(a);
values.add(b);
values.add(c);
values.add(d);
values.add(e);
values.add(g);
values = enrichValues(values);
System.out.println(values.toString());
}
Output : [Aa123, Cc123, 15Bb2, Hhkjk124, hy71, AabCcdEe645 DdeeeFfFfDd]
When you are writing some method which accepts concrete implementation of the List interface such as ArrayList, consider to change it to List type. This will allow you to pass in any form of list: LinkedList, ArrayList, ...
Another thing you shoud know is, that joining strings via += is inefficient, as it creates new String instance each time += is applied. Instead of doing this, you should use StringBuilder which allocates resizable buffer for string where you can append other characters.
Condition Character.isLetter(c) && Character.isUpperCase(c) is redudant, since Character.isUpperCase(char) already returns false for non-letter characters.
If you need to convert character to lower-case use Character.toLowerCase(char).
Note, characters are basically integers, so when you write something like this: char c = 65; and print the value, you will see 'A' in output, because 65 is ASCII value for character 'A'. If you add 32, you will obtain 97 which is 'a'. Putting all together you can write something like this:
char c = ...;
// c is in range of upper-case characters
if (c >= 65 && c <= 90) {
char lower = c + 32;
}
// c is in range of lower-case characters
if (c >= 97 && c <= 122) {
char upper = c - 32;
}
Try following method which mutates original list:
protected List<String> enrichValues(List<String> list) {
for (int i = 0; i < list.size(); i++) {
StringBuilder sb = new StringBuilder(list.get(i));
for (int j = 0; j < sb.length(); j++) {
char c = sb.charAt(j);
if ( Character.isUpperCase(c) ) {
sb.insert(++j, Character.toLowerCase(c));
}
}
list.set(i, sb.toString());
}
return list;
}
or this one which creates new list for transformed values:
protected List<String> enrichValues(List<String> original) {
List<String> transformed = new ArrayList<>(list.size());
for (String s : original) {
StringBuilder sb = new StringBuilder(s);
for (int j = 0; j < sb.length(); j++) {
char c = sb.charAt(j);
if ( Character.isUpperCase(c) ) {
sb.insert(++j, Character.toLowerCase(c));
}
}
transformed.add(sb.toString());
}
return transformed;
}
Test:
System.out.println( enrichValues(Arrays.asList("A123", "C123", "15B2")) );
// Output: [Aa123, Cc123, 15Bb2]
To find out whether if a letter is upper case you just need to use the ASCII alphabet. Upper case characters go from 65 to 90.
So you just need to use a loop over the length of your string and check for each char if it´s ASCII value is between 65 and 90. So it would look like this, assuming the variable temp is one character of the string:
if((int)temp >= 65 && (int)temp <= 90){
//Add the lower case character by adding 22 to the character value (lower case are from 97-122)
char additionalChar = ((int)temp)+22;
}
Note that I´ve not tried the code so ((int)temp)+22 might not work that way, but it would look pretty similar.
There is an easier way to do this with regular expressions:
final ArrayList< String > outputList = new ArrayList<>();
for ( String str : list ) {
final String[] letters = str.replaceAll( "[^A-Z]", "" ).toLowerCase().split( "" );
final String result = String.format( str.replaceAll( "([A-Z])", "$1%s" ), letters );
outputList.add( result );
}
return outputList;
I am trying to find out that if my string contains all the letters from a to z & A to Z. I tried below: but it will return true if it has aA. I am looking for all the 52 letters i.e. if string have all 52 letters then only it will return true else false by using Pattern and matcher.
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
s=s.replaceAll("\\s+", "");
System.out.println(s);
// String input = "[a-zA-Z]+";
String input = "\\w+";
System.out.println(input);
Pattern pr = Pattern.compile(input);
Matcher m =pr.matcher(s);
if(m.matches()){
System.out.println("pangram");
} else {
System.out.println("non-pangram");
}
We can solve this by other ways, but I am trying to solve it by only using Pattern and matcher.
If you want to see if all 52 upper- and lower-case letters are present in a given input string, you can't use a regular expression. It simply cannot do something like that.
If the list of characters that must be present is dynamic, you can use this method:
private static boolean containsAllOf(String input, String alphabet) {
boolean[] found = new boolean[alphabet.length()];
int foundCount = 0;
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
int idx = alphabet.indexOf(ch);
if (idx >= 0 && ! found[idx]) {
found[idx] = true;
if (++foundCount == found.length)
return true;
}
}
return false;
}
E.g. use it like this:
containsAllOf("abc", "abcdef") // returns false
containsAllOf("dfu hadkf kojuhoeuaf", "abcdef") // returns false
containsAllOf("bad fed", "abcdef") // returns false
containsAllOf("bad fec", "abcdef") // returns true
Performance can be improved if you specifically want to check the entire 52 upper- and lower-case letters of the English alphabet.
private static boolean containsAllOfAlphabet(String input) {
boolean[] found = new boolean[52];
int foundCount = 0;
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
int idx = (ch >= 'a' && ch <= 'z' ? ch - 'a' :
ch >= 'A' && ch <= 'Z' ? ch - 'A' + 26 : -1);
if (idx >= 0 && ! found[idx]) {
found[idx] = true;
if (++foundCount == found.length)
return true;
}
}
return false;
}
UPDATE If you want to use a pattern matcher, here is one way.
Start by sorting all the characters of the input string, then use a pattern matcher to eliminate all non-letters and duplicate letters. If the length of the result is 52, then all letters are present.
Of course, a pangram normally don't consider uppercase and lowercase letters to be different, so calling toLowercase() and checking for length 26 may be more correct:
String input = "Pack my box with five dozen liquor jugs.";
char[] buf = input.toLowerCase().toCharArray();
Arrays.sort(buf);
boolean pangram = (new String(buf).replaceAll("[^a-zA-Z]|([a-zA-Z])\\1+", "$1").length() == 26);
System.out.println(pangram ? "pangram" : "non-pangram");
I have used set and putting the every character(ASC) in it, as Set only contains the unique values so I am checking size == 26 for all characters. use if(put>=97 && put<=122 ) before adding.
Scanner sc = new Scanner(System.in);
String s= sc.nextLine();
Set<Integer> h = new HashSet<Integer>();
for (int i = 0; i < s.length(); i++) {
int put = (int)s.charAt(i);
if(put>=97 && put<=122 ) {
h.add(put);
}
if(put>=65 && put<=90 ) {
h.add(put);
}
}
if(h.size()==52)
System.out.println("all 52");
else
System.out.println("missing");
I am trying to figure out how to write a method that will remove letters in a
string based on another string. The method would end up like so:
removeLetter("file", "fe")
The only thing that should be returned is the string "il". So far I have something like this:
public class h
{
public static void main(String[] args)
{
String a="file";
String b="fe";
char letter;
int i;
int j;
for (letter = 'a'; letter <= 'z'; letter++)
{
for (i=0; i < a.length()-1; i++)
{
for (j=0; j < b.length()-1; j++) // This is the loop i get stuck on
{
char r = b.charAt(j);
char s = a.charAt(i);
if ( letter == r && letter == s);
System.out.print(r + " " + s);
}
}
}
}
}
I know the bottom part is wrong but I am not sure where to go from here.
You can do this with a regular expression:
a.replaceAll("[" + b + "]", "")
This works by constructing a character class like [fe], and replacing characters which match that with the empty string.
Of course, this is a bit of a hack, in that you can easily choose b such that it won't yield a valid regular expression. However, if you know that b will only ever contain letters, this would work.
Here's a pretty simple nested array using a flag boolean :
public static void main(String[] args) {
String a = "file";
String b = "f";
String c = "";
StringBuilder sb = new StringBuilder();
boolean contains;
for (int i = 0 ; i < a.length() ; i++){
contains = false;
for (int j = 0 ; j < b.length() ; j++){
if (a.charAt(i) == b.charAt(j)) contains = true;
}
if (!contains) sb.append(a.charAt(i));
}
System.out.println(sb);
}
It checks every char of the first word with the chars of the second and changes the flag to true if the char is contained in both.
If it is not the case, the char of the first word is added to the new String, if the contrary, nothing happens and we continue to the next char of the first String.
Let's remove all the vowels of this word : Supercalifragilisticexpialidocious
String a = "Supercalifragilisticexpialidocious";
String b = "aeiou";
Here's the output :
Sprclfrglstcxpldcs
At input i have some string : "today snowing know " , here i have 3 words , so i must to parse them is such way : every character i must compare with all other characters , and to sum how many same characters these words have , like exemple for "o" letter will be 2 (from "today" and "snowing") or "w" letter will be 2 (from "know" and "snowing"). After that i must to replace these characters with number(transformed in char format) of letters. The result should be "13111 133211 1332".
What i did ?
First i tape some words and
public void inputStringsForThreads () {
boolean flag;
do {
// will invite to input
stringToParse = Input.value();
try {
flag = true;
// in case that found nothing , space , number and other special character , throws an exception
if (stringToParse.equals("") | stringToParse.startsWith(" ") | stringToParse.matches(".*[0-9].*") | stringToParse.matches(".*[~`!##$%^&*()-+={};:',.<>?/'_].*"))
throw new MyStringException(stringToParse);
else analizeString(stringToParse);
}
catch (MyStringException exception) {
stringToParse = null;
flag = false;
exception.AnalizeException();
}
}
while (!flag);
}
I eliminate spaces between words , and from those words make just one
static void analizeString (String someString) {
// + sign treat many spaces as one
String delimitator = " +";
// words is a String Array
words = someString.split(delimitator);
// temp is a string , will contain a single word
temp = someString.replaceAll("[^a-z^A-Z]","");
System.out.println("=============== Words are : ===============");
for (int i=0;i<words.length;i++)
System.out.println((i+1)+")"+words[i]);
}
So i try to compare for every word in part (every word is split in letters) with all letter from all words , But i don know how to count number of same letter and after replace letters with correct number of each letter??? Any ideas ?
// this will containt characters for every word in part
char[] motot = words[id].toCharArray();
// this will containt all characters from all words
char[] notot = temp.toCharArray();
for (int i =0;i<words[i].length();i++)
for (int j=0;j<temp.length ;j++)
{
if (i == j) {
System.out.println("Same word");
}
else if (motot[i] == notot[j] ) {
System.out.println("Found equal :"+lol[i]+" "+lol1[j]);
}}
For counting you might want to use a Map<Character, Integer> counter like java.util.HashMap. If getting a Value(Integer) using a specific key (Character) from counter is 'not null', then your value++ (leverage autoboxing). Otherwise put a new entry (char, 1) in the counter.
Replacing the letters with the numbers should be fairly easy then.
It is better to use Pattern Matching like this:
initially..
private Matcher matcher;
Pattern regexPattern = Pattern.compile( pattern );
matcher = regexPattern.matcher("");
for multiple patterns to match.
private final String[] patterns = new String [] {/* instantiate patterns here..*/}
private Matcher matchers[];
for ( int i = 0; i < patterns.length; i++) {
Pattern regexPattern = Pattern.compile( pattern[i] );
matchers[i] = regexPattern.matcher("");
}
and then for matching pattern.. you do this..
if(matcher.reset(charBuffer).find() ) {//matching pattern.}
for multiple matcher check.
for ( int i = 0; i < matchers.length; i++ ) if(matchers[i].reset(charBuffer).find() ) {//matching pattern.}
Don't use string matching, not efficient.
Always use CharBuffer instead of String.
Here is some C# code (which is reasonably similar to Java):
void replace(string s){
Dictionary<char, int> counts = new Dictionary<char, int>();
foreach(char c in s){
// skip spaces
if(c == ' ') continue;
// update count for char c
if(!counts.ContainsKey(c)) counts.Add(c, 1);
else counts[c]++;
}
// replace characters in s
for(int i = 0; i < s.Length; i++)
if(s[i] != ' ')
s[i] = counts[s[i]];
}
Pay attention to immutable strings in the second loop. Might want to use a StringBuilder of some sort.
Here is a solution that works for lower case strings only. Horrible horrible code, but I was trying to see how few lines I could write a solution in.
public static String letterCount(String in) {
StringBuilder out = new StringBuilder(in.length() * 2);
int[] count = new int[26];
for (int t = 1; t >= 0; t--)
for (int i = 0; i < in.length(); i++) {
if (in.charAt(i) != ' ') count[in.charAt(i) - 'a'] += t;
out.append((in.charAt(i) != ' ') ? "" + count[in.charAt(i) - 'a'] : " ");
}
return out.substring(in.length());
}