How to search the largest string in an array of strings - java

I need to find the largest string from an array of strings and also want to make sure that the string which comes out should include only those chars which are defined in a separate string.
For eg: if an array of strings contains {"ABCAD","ABC","ABCFHG","AB"}
and another string S have chars "ABCD".
Then the largest string return here should be ABCAD as it contains only the characters defined in S.
public String findstring(String a, String[] arr)
{
String s="";
for(i=0; i<arr.length; i++)
{
//int m=0;
if(arr[i].length() > s.length())
{
s = arr[i];
}
}
for(j=0; j<s.length(); j++)
{
int m=0;
for(k=0; k<a.length(); k++)
{
if(m>0)
{
break;
}
if((s.charAt(j)==a.charAt(k)))
{
m++;
}
else
{
continue;
}
}
if(m==0)
{
List<String> list = new ArrayList<String>(Arrays.asList(arr));
list.remove(s);
arr = list.toArray(new String[0]);
findstring("ABCD", arr);
}
}
return s;
}
}
I am not receiving any error and getting the largest string as ABCFABCD whereas F needs to be excluded and largest string should be ABCAA.
Its skipping all the checks, don't know why?

You can do it in better way using Regex:
public String findstring(final String a, final String[] arr) {
String s = "";
// Created pattern of the characters available in the String
final Pattern p = Pattern.compile("^[" + a + "]*$");
for (int i = 0; i < arr.length; i++) {
if (p.matcher(arr[i]).matches()) {
if ("".equals(s)) {
s = arr[i];
} else if (arr[i].length() > s.length()) {
s = arr[i];
}
}
}
return s;
}

You make recursive call but just ignore the returned value.
Try add return on recursive findstring.
arr = list.toArray(new String[0]);
return findstring("ABCD", arr);

If you want to have the luxury of New & Much Better Java Powers with some elegant, readable and less lines of code... you can have a look at below snippet:
public static void main(String args[]) {
final String allowedChars = "ABCD";
final char[] chars = allowedChars.toCharArray();
String result = Stream.of("ABCAD","ABC","ABCFHG","AB")
.filter(s ->{
for(char c: chars){
if(!s.contains(c+""))
return false;
}
return true;
})
.max(Comparator.comparingInt(String::length))
.orElse("No Such Value Found");
System.out.println("Longes Valid String : " + result);
}
Explanation:
The code makes a Stream of String from arrays and filter only valid strings (Strings which are not containing the allowed characters will simply be removed from the further processing) and remaining Stream will be compared for the length (using Comparator), and finally, longest valid String will be returned.
There may be a case where all the strings in array/Stream would be invalid, in such case, the code will return the Message "No Such Value Found" as String, however you can throw an exception, or you can return some own value for your custom logic, or you can return null, etc.
I've intentionally kept the String message and gave you the hint about learning other methods present in Java Stream so that you can explore more.
Keep Coding... and feel the Power of New JAVA. :)

Related

I'm stuck. I need to adjust my loops so they continue to compare my two arrays but not print out all the extra characters

I have to compare two string arrays. If the any of the characters in myArray match a character in argArray then I need to swap the case of the character in myArray. I'm almost there but am getting extra output.
This is what I have so far -
public class Main {
public static void main(String[] args) {
Main ob = new Main();
ob.reverse("bcdxyz#3210.");
}
public String reverse(String arg) {
String reverseCap = "";
String myStr = "abc, XYZ; 123.";
char[] argArray = arg.toCharArray();
char[] myArray = myStr.toCharArray();
for (int i =0; i < myArray.length; i++) {
for (int j =0; j < argArray.length; j++){
if (myArray[i] == argArray[j] && Character.isLowerCase(myArray[i])){
reverseCap += Character.toUpperCase(myArray[i]);
} else if (myArray[i] == argArray[j] && Character.isUpperCase(myArray[i])){
reverseCap += Character.toLowerCase(myArray[i]);
} else {
reverseCap += myArray[i];
}
}
}
System.out.println(reverseCap);
return null;
}
I want reverseCap to be "aBC, xyz, 123." but am getting the following -
"aaaaaaaaaaaaBbbbbbbbbbbbcCcccccccccc,,,,,,,,,,,, XXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZZZZZ;;;;;;;;;;;; 111111111111222222222222333333333333............
".
I've been staring at this for hours so I figured it was time to ask for help before I pluck my eyes out.
Marce noted the problem of adding characters to reverseCap on every iteration. Here is a solution that solves that problem and performs the case changes in place. Checking for a match first and then changing the case simplifies the logic a bit. Note myArray[i] needs to be lowercased before checking against arg[i] because the former may be an uppercase character; this is not needed for argArray[j] because those characters are assumed to be all lowercase. Finally, once the inner loop has matched, further iterations of it are no longer needed.
public class Main {
public static void main(String[] args) {
Main ob = new Main();
String testStr = "abc, XYZ; 123.";
String testArg = "bcdxyz#3210.";
System.out.println(testStr + " using " + testArg + " =>");
System.out.println(ob.reverse(testStr, testArg));
}
public String reverse(String myStr, String myArg) {
char[] myArray = myStr.toCharArray();
char[] argArray = myArg.toCharArray();
for (int i =0; i < myArray.length; i++) {
for (int j =0; j < argArray.length; j++) {
if (Character.toLowerCase(myArray[i]) == argArray[j]) {
if (Character.isLowerCase(myArray[i])) {
myArray[i] = Character.toUpperCase(myArray[i]);
} else if (Character.isUpperCase(myArray[i])) {
myArray[i] = Character.toLowerCase(myArray[i]);
}
break;
}
}
}
return String.valueOf(myArray);
}
}
With this part
} else {
reverseCap += myArray[i];
}
you're adding a character to reverseCap with every iteration, regardless if the characters match or not.
In your specific example, you could just leave that out, since every character in myStr also appears in arg, but if you want to add characters to reverseCap, even if they don't appear in arg, you'll need a way of checking if you already added a character to reverseCap.
Change
String reverseCap = "";
to
char[] reverseCap = new char[myStr.length()];
and then for each occurrence of
reverseCap +=
change that to read
reverseCap[i] =
Finally, convert reverseCap to a String:
String result = String.valueOf(reverseCap);
You are currently returning null. Consider returning result, and moving the System.out.println(...) into the main() method.
Update:
I think a better way to approach this is to use a lookup map containing upper/lower case pairs and their inverse to get the replacement character. The nested for loops are a bit gnarly.
/**
* Example: for the string "bcdxyz#3210."
* the lookup map is
* {B=b, b=B, C=c, c=C, D=d, d=D, X=x, x=X, Y=y, y=Y, Z=z, z=Z}
* <p>
* Using a map to get the inverse of a character is faster than repetitively
* looping through the string.
* </p>
* #param arg
* #return
*/
public String reverse2(String arg) {
Map<Character, Character> inverseLookup = createInverseLookupMap(arg);
String myStr = "abc, XYZ; 123.";
String result = myStr.chars()
.mapToObj(ch -> Character.toString(inverseLookup.getOrDefault(ch, (char) ch)))
.collect(Collectors.joining());
return result;
}
private Map<Character, Character> createInverseLookupMap(String arg) {
Map<Character, Character> lookupMap = arg.chars()
.filter(ch -> Character.isLetter(ch))
.mapToObj(this::getPairs)
.flatMap(List::stream)
.collect(Collectors.toMap(Pair::key, Pair::value));
System.out.println(lookupMap);
return lookupMap;
}
private List<Pair> getPairs(int ch) {
char upperVariant = (char) Character.toUpperCase(ch);
return List.of(
new Pair(upperVariant, Character.toLowerCase(upperVariant)),
new Pair(Character.toLowerCase(upperVariant), upperVariant));
}
static record Pair(Character key, Character value) {
}
But if one is not used to the Java streaming API, this might look a bit gnarly too.

if the characters are same then consider it only once in java language

So, i am basically new to java ,and there was this question on our programming test
input:ww:ii:pp:rr:oo
if the alphabets are same then consider only once
output:wipro
so i was able to remove the : from the input and was also able to separate them
my current output :[w,w,i,i,p,p,r,r,o,o]
but i am unable to consider the same characters only once,its been nearly 35 min :_(
String txt="ww:ii:pp::rr:oo";
String[] result= txt.split(":");
System.out.println(Arrays.toString(result));//1
String n11="";
for(String str:result){
n11 += str;
}
System.out.println(n11);//2
result=n11.split("");
System.out.println(Arrays.toString(result));//3
String n12="";
int i=0;
for(String i:result){
if(i.equals(i+1)){
continue;
}
else {
n12=n12+i;
}
}
System.out.println(n12);//4
}
output
[ww, ii, pp, , rr, oo]
wwiipprroo
[w, w, i, i, p, p, r, r, o, o]
[nullw, nullw, nulli, nulli, nullp, nullp, nullr, nullr, nullo, nullo]
Example:
public class GFG
{
/* Method to remove duplicates in a sorted array */
static String removeDupsSorted(String str)
{
int res_ind = 1, ip_ind = 1;
// Character array for removal of duplicate characters
char arr[] = str.toCharArray();
/* In place removal of duplicate characters*/
while (ip_ind != arr.length)
{
if(arr[ip_ind] != arr[ip_ind-1])
{
arr[res_ind] = arr[ip_ind];
res_ind++;
}
ip_ind++;
}
str = new String(arr);
return str.substring(0,res_ind);
}
/* Method removes duplicate characters from the string
This function work in-place and fills null characters
in the extra space left */
static String removeDups(String str)
{
// Sort the character array
char temp[] = str.toCharArray();
//Arrays.sort(temp);
str = new String(temp);
// Remove duplicates from sorted
return removeDupsSorted(str);
}
// Driver Method
public static void main(String[] args)
{
String str = "ww:ii:pp:rr:oo";
String str1 = str.replaceAll(":","");
System.out.println(removeDups(str1));
}
}
The source is taken from www.geeksforgeeks.org And added String str1 = str.replaceAll(":","");
Output:
Your first step is right. But, you have an error in i.equals(i+1) since i + 1 isn't is the next element. You should iterate the array like this:
for (int i = 0; i < result.length - 1; i ++) {
if (result[i].equals(result[i + 1])) {
// do the remove operation.
}
}

Java: Formatting issue. Grabbing unique characters from an array of strings and returning them

I'm having a problem getting the unique letters and digits out of an array of strings, and then returning them. I am having a formatting issue.
The given input is: ([abc, 123, efg]) and is supposed to return abcefg123,
however, mine returns: abc123efg
how can I fix this since arrays.sort() will end up putting the numbers first and not last?
Here is my method so far:
public static String getUniqueCharsAndDigits(String[] arr) {
String str = String.join(",", arr);
String myString = "";
myString = str.replaceAll("[^a-zA-Z0-9]", "");
for(int i = 0; i < str.length(); i++) {
if(Character.isLetterOrDigit((i))){
if(myString.indexOf(str.charAt(i)) == -1) {
myString = myString + str.charAt(i);
}
}
}
return myString;
}
What you want to do is create two strings, one with the letters, one with the digits.
public static String getUniqueCharsAndDigits(String[] arr) {
String str = String.join("", arr);
String myLetters, myDigits;
myLetters = myDigits = "";
for(int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(Character.isLetter(c)){
if(myLetters.indexOf(c) == -1) {
myLetters += c;
}
} else if(Character.isDigit(c)){
if(myDigits.indexOf(c) == -1) {
myDigits += c;
}
}
}
//if they need to be sorted, sort each one individually here
return myLetters + myDigits;
}
I've modified your code and deleted the unnecessary parts of it.

filtering algorithm trouble

public static String filterPhoneNumber(String phoneNumber) {
Character[] characters = new Character[phoneNumber.length()];
if (characters.length > 9)
{
for (int i = 0; i < characters.length; i++)
{
if (characters[i] != ' ')
{
characters[i] = phoneNumber.charAt(i);
} else
{
Log.d("asd", "wrroooonggggggggg");
}
}
}
return phoneNumber;
}
Im trying to filter empty chars in the number, but when 2 or more empty chars are found in the string, it removes only the first.
Your problem is that you increase i in the for-loop and when you find a space you skip it. When you in the next loop set the number in characters you have skipped one entry. You must use two stepping variables, one for stepping phoneNumber and one for characters.
It looks like you want to return a filter phone number, but are returning the values that you sent in.
There is a search and replace method on String that you can use.
public static String filterPhoneNumber(String phoneNumber) {
return phoneNumber.replaceAll(" ","");
}
Here is how it is used: http://runnable.com/VUfHvPvHoEdLO3id/filterphonenumber-for-java
If you use
char[] characters = new char[phoneNumber.length()];
it works.
your characters array should be of the type char[]
characters array is never initialized, so characters[i] != ' ' is always true (provided that you fix the array type, else should throw a NullPointerException)
you're assign characters[i] = phoneNumber.charAt(i) but you never read it afterwards.
If your goal is to remove spaces just do this:
public static String filterPhoneNumber(String phoneNumber) {
return phoneNumber.replaceAll(" ", "");
}
Working 100%
public static String filterPhoneNumber(String phoneNumber) {
byte[] number = phoneNumber.getBytes();
byte[] array = new byte[phoneNumber.length()];
int count=0;
for (int i = 0; i < number.length; i++){
if (number[i] != ' '){
array[count++] = number[i];
}
}
return new String(array);
}
public static void main(String[] args) {
String res = filterPhoneNumber(" +28 23");
System.out.println(res); //OUTPUT "+2823"
}

How to return a String Array

My code is supposed to separate a given String and covert the chosen letters into # and separate and concatenate the words with the chosen letter. My problem is with one of the methods (allWordsWith) in my code, it won't allow me to return a String array. (p.s, the codes that run this one are irrelevant, I'm not supposed to edit those).
import java.util.Arrays;
import java.util.Scanner;
public class LipogramAnalyzer {
private String line;
public LipogramAnalyzer(String text){
line = text;
}
public String mark (char letter){
String replaceletters = line.replace(letter, '#');
return replaceletters;
}
public String[] allWordsWith (char letter){
String[] arr = line.split(" ");
for ( String ss : arr) {
String ary[] = {ss};
for(int i = 0; i < ary.length; i++){
int numindex = ss.indexOf(letter);
if (numindex != -1){
String result = ary[i];
return result;
}
}
}
}
}
"It won't allow me to return a String array"
Sure it will. You're attempting to return a String:
String result = ary[i];
return result;
Even though the return type is a string array:
public String[] allWordsWith (char letter){
You need to return an array, as allWordsWith implies you want multiple values.
But the bigger problem is that you are initializing the result array to a single element
String ary[] = {ss};
and thes lengths of arrays can't be changed after initialization. This means that ary.length in this loop
for(int i = 0; i < ary.length; i++){
will always equal one. That is not what you want.
In addition, you are searching the strings in the result array (ary), even though you just created it, meaning it has nothing in it--that is, all the values are null.
If you want a list of all the strings in line that have the letter in it, try
public String[] allWordsWith (char letter){
String[] asAllWordsInLine = line.split(" ");
java.util.ArrayList<String> alsAllWordsWithChar = new java.util.ArrayList<String>();
for ( String ss : asAllWordsInLine) {
if(ss.indexOf(letter) != -1) {
alsAllWordsWithChar.add(ss);
continue; //No need to check any more letters.
}
}
return alsAllWordsWithChar.toArray(new String[alsAllWordsWithChar.size()]);
}
I've changed the array to a list, since you can't know how many strings will have letter in it. A list can change size, an array can't. When no strings match, this returns an empty array, which is preferred over null. (more info)
I've also made the variable names more meaningful, and stopped checking a word after it matches a character (with continue, which short-circuits the current for-loop iteration).
Finally, the function is not returning anything until all strings have been analyzed, meaning after the for-loop completes. In your original code the return is inside the loop, meaning only the first string is returned.
A useful testing function:
public static final void main(String[] igno_red) {
testLine('b', "abc def ghi cba def ghi");
}
private static final void testLine(char c_letter, String s_line) {
System.out.println("Line: \"" + s_line + "\"");
String[] asAllWordsWith = (new LipogramAnalyzer(s_line)).allWordsWith(c_letter);
System.out.println("Words with '" + c_letter + "': " + Arrays.toString(asAllWordsWith));
}
Return the ary not ary[i]
for(int i = 0; i < ary.length; i++){
int numindex = ss.indexOf(letter);
if (numindex != -1){
String result = ary[i];
/*here*/ return ary;
}
You can return an array. Try return ary instead of return ary[i].
Also, your function must return something in all cases. In other words, you have to have a return statement after your for loops.
public String[] allWordsWith (char letter){
String[] arr = line.split(" ");
for ( String ss : arr) {
String ary[] = {ss};
for(int i = 0; i < ary.length; i++){
int numindex = ss.indexOf(letter);
if (numindex != -1){
String result = ary[i];
// or here return ary;
}
}
}
return ary;
}
Return the array
You are trying to return a String instead of String[] (String array)
Change the code:
if (numindex != -1) {
String result = ary[i];
return result;
}
To:
if (numindex != -1) {
return new String[]{ary[i]};
}
// afrer first for loop
return arr;
If you want to return a complete String-Array at once, I have modified your function (not tested):
public String[] allWordsWith (char letter){
String[] arr = line.split(" ");
String[] result = new String[ary.length];
for ( String ss : arr) {
String ary[] = {ss};
for(int i = 0; i < ary.length; i++){
int numindex = ss.indexOf(letter);
if (numindex != -1){
result[i] = ary[i];
}
}
}
return result;
}
As already said, you're returning a String instead of a String[]. Also note that your code will only ever return a single "word". I modified your code to add every word that contains your character and add it to a List. At the end of the loop the List is converted to a String[].
public String[] allWordsWith(char letter)
{
String[] arr = line.split(" ");
List<String> result = new ArrayList<>();
for (String ss : arr) {
int numindex = ss.indexOf(letter);
if (numindex != -1) {
result.add(ss);
}
}
return result.toArray(new String[result.size()]);
}

Categories

Resources