In this program, I have to use the concept of polymorphism,
I have 1 abstract superclass named Data, and 2 subclasses named List and Single. Single accepts a double value(Constructor: public Single(value)). List accepts an array of doubles.( Constructor: List(double[] arr)), and in my main method, the following array,...
public static void main(String[] args) {
Object[] mixedData = {
new Single(2.4),
"The data is 3.6",
new List(new double[] {3.2,6.8}),
"Nothing here at all",
new List(new double[] {1.2,7.9,4.5}),
"Anda 1 anda 2 anda 3",
new Single(9.8) };
I have to convert this Object[] array into Data[] array using a method:
public static Data[] convert(Object[] objects){
final int MAX_LIST_SIZE = 10;
//***** YOUR CODE HERE *****
objects= new Object[MAX_LIST_SIZE];
Data[] data= new Data[MAX_LIST_SIZE];
data = (Data[]) objects;
for(int i=0; i<data.length; i++) {
}
return null; //Dummy statement - replace it
}
In this method,
1)we have to make sure that both arrays are of same length.
2)Use shallow copy
3)If there is a String(if it contains a number), then change it to List object, containing all the numbers that can be found(as separate tokens) in the String. Use a Scanner to scan the String for
numbers. Non-numbers should be ignored.
My Only doubt is that, in mixedData array, how can I find if it contains a String.
hope someone will answer.
I added some comments to your code to guide you through the solution.
public static Data[] convert(Object[] objects){
// If the objects array contains more than 10 elements what to do?
// final int MAX_LIST_SIZE = 10;
// Here you clear the content of the input objects, why?
//objects= new Object[MAX_LIST_SIZE];
// Set the length of data to the length of the input object array
Data[] data= new Data[objects.length];
// This cannot be done
// data = (Data[]) objects;
for(int i=0; i<objects.length; i++) {
if(objects[i] instanceof Single) {
data[i] = (Single) objects[i];
}else if(objects[i] instanceof List) {
data[i] = (List) objects[i];
}else if(objects[i] instanceof String) {
String string = (String) objects[i];
// Find all doubles with Scanner
// Add the doubles to a List
// Add the List to data[i]
}
}
return data;
}
Since both arrays are of same length, you have to decide how to handle an array element that doesn't contain a decimal number. For example, the interned String object "Nothing here at all" doesn't contain any numerical values, so once we process the string, it will return a null value.
Shallow copy: since the field is a primitive type (double), use the = operator to assign its value to the array at the right index.
You can change the code easily to implement the use of a Scanner to scan the String for numbers as required. Create a new scanner object and pass the string you're processing in the constructor.
/**
* Output:
* Single obj: 2.4
* Single obj: 3.6
* List obj: 3.2 6.8
* Data obj: null
* List obj: 1.2 7.9 4.5
* List obj: 1.0 2.0 3.0
* Single obj: 9.8
*
* #author martinfall
*/
public class TestData {
public static void main(String[] args) {
// Given
Object[] mixedData = {
new Single(2.4),
"The data is 3.6",
new List(new double[]{3.2, 6.8}),
"Nothing here at all",
new List(new double[]{1.2, 7.9, 4.5}),
"Anda 1 anda 2 anda 3",
new Single(9.8)};
// Convert mixedData and assign the result to a Data array
Data[] arr = convert(mixedData);
// Print to console (Not required but helpful to see the output of each obj)
for (Data datum : arr) {
if (datum instanceof Single) {
System.out.print("Single obj: ");
System.out.println(((Single) datum).value); // Can encapsulate
} else if (datum instanceof List) {
System.out.print("List obj: ");
for (double num : ((List) datum).arr) {
System.out.print(num + " ");
}
System.out.println();
} else {
// Since required that both arrays be equal size,
// not sure how to handle an element of mixedData that doesn't
// contain any decimal numbers
System.out.println("Data obj: " + datum);
}
}
}
public static Data[] convert(Object[] objects) {
// Find the length of objects and assign it to MAX_LIST_SIZE
final int MAX_LIST_SIZE = objects.length;
// Create a new array of Data objects using the length of objects
Data[] arr = new Data[MAX_LIST_SIZE];
// Loop throught the array and copy each element as required
for (int i = 0; i < MAX_LIST_SIZE; i++) {
if (objects[i] instanceof Single) {
arr[i] = (Data) objects[i]; // Shallow copy
} else if (objects[i] instanceof List) {
arr[i] = (Data) objects[i];
} else if (objects[i] instanceof String) {
// Since both arrays have to be the same length, we have to add
// the null value that is returned if a string doesn't contain
// a numerical value
arr[i] = processString((String) objects[i]);
}
}
return arr;
}
public static Data processString(String str) {
// Regular expression to match double values
String regex = "^[-+]?\\d*(\\.\\d+)?$";
// Counter variable to use to find out if list or single is returned
int count = 0;
// Create a blank Data variable
Data d = null;
// Split the String
String[] split = str.split(" ");
// Determine if Single or List
for (String s : split) {
if (s.matches(regex)) {
count++;
}
}
// If count is 1, return a Single
if (count == 1) {
for (String s : split) {
if (s.matches(regex)) {
d = new Single(Double.parseDouble(s));
}
}
} else if (count > 1) {
// Create a new array as large as count
double[] arr = new double[count];
// Index of arr
int arrIndex = 0;
for (String s : split) {
if (s.matches(regex)) {
arr[arrIndex] = Double.parseDouble(s);
arrIndex++;
}
}
d = new List(arr);
}
return (Data) d;
}
}
Related
I have a .txt file which has data for states as given below:
AL,Alab,4860
AK,Alas,7415
AZ,Ariz,6908
AR,Arka,2988
I have made a function which counts how many states there are that start with the initial passed as such:
public int CInitial(char initial) {
int total = 0;
for(int i = 0; i < states.length; i++) { //states is an array which includes all states present in the .txt file
String testString = states[i].getName(); // getName gets the name of the states present in the .txt file
char[] stringToCharArray = testString.toCharArray();
for (char output : stringToCharArray) {
if(initial == output) {
total++;
}
}
}
return total;
}
This would return the number 4 if "A" is passed and 0 if any other initial is passed as there are 4 states that begin with the letter "A".
Now how can I create a new function that passes a character and returns the name of all the states that begin with that character? For Instance this is the initial return type needed for this, however I'm having troubles starting this. Is the process identical to the countStatesCountByInitial function I created?
public State[] CByInitial(char initial) {
return new State[] {}; //to be completed
}
Yes, it will be very similar to the countStatesCountByInitial. The main difference is each time you find a match, you want to add the state into the array. Since we don't know the size of the array beforehand, we may want to use a List instead.
public State[] getStatesCountByInitial(char initial) {
ArrayList<State> found = new ArrayList<>();
// this is the same as before
for(int i = 0; i < states.length; i++) {
String testString = states[i].getName();
char[] stringToCharArray = testString.toCharArray();
for (char output : stringToCharArray) {
if(initial == output) {
// except here when you find a match, you add it into the list
found.add(states[i]);
}
}
}
// return as array
return found.toArray(new State[found.size()]);
}
As suggested by Patrick, we can avoid using List by using countStatesCountByInitial to initialize the size of the states.
public State[] getStatesCountByInitial(char initial) {
int matchSize = countStatesCountByInitial(initial);
States[] found = new States[matchSize];
int foundIndex = 0;
// this is the same as before
for(int i = 0; i < states.length; i++) {
String testString = states[i].getName();
char[] stringToCharArray = testString.toCharArray();
for (char output : stringToCharArray) {
if(initial == output) {
// except here when you find a match, you add it into the array
found[foundIndex] = states[i];
foundIndex++;
}
}
}
// return the array
return found;
}
You can done both operations simply by one method.
public static ArrayList<State> getStatesCountByInitial(char initial) {
ArrayList selectedStates = new ArrayList<State>();
for(int i = 0; i < states.length; i++) {
if(states.charAt(0) == initial){
selectedStates.add(states[i]);
}
}
return selectedStates;
}
This method will return a arraylist.
If you want to get the count, call this method and get the size of the array.
ArrayList<State> statesNew = getStatesCountByInitial('A');
int count = statesNew.size();
here is my code and I need to remove a fruit from the array
public void delete(String fruitName) {
for (int i = 0; i < fruits.length; i++) {
if ( fruits[i].equals(fruitName)) {
fruits[i] = fruits[i+1];
break;
}
}
// ["banana", "apple, "Mango"] if removed banana then output ["apple", "Mango"].
// TODO: 1. implement this method.
/* TODO: 2. you may need to consult Java API documentation for the String class.
* Write a comment in the code, the method of the String class you
* look up and the URL to the documentation the method
*/
}
"Working code Example : "(Execution)
public class DeleteValue {
String fruits[] = { "apple", "orange", "banana", "mango", "Cherries", "Blueberries" }; // array of fruits
public void delete(String fruitName) {
// printing array of fruits before deletion
System.out.println("\nAvailable fruits Before delete : " + fruits.length + "\n");
for (String s : fruits) {
System.out.println(s + " is Available\n");
}
int length = fruits.length;
int lengthNew = length;
int countNull = 0;
// 1. Find and delete the fruit
for (int i = 0; i < fruits.length; i++) {
if (fruits[i] == fruitName) {
fruits[i] = null;
break;
}
}
// count the null or deleted values so that we can create a new array of length
// minus the deleted fruit
for (int i = 0; i < fruits.length; i++) {
if (fruits[i] == null) {
countNull++;
}
}
// new array length
lengthNew = lengthNew - countNull;
// create new array of fruits
String newFruits[] = new String[lengthNew];
// assigning values from original array to new
int j = 0;
for (int i = 0; i < fruits.length; i++) {
if (fruits[i] == null) {
continue;
}
if (fruits[i] != null) {
newFruits[j] = fruits[i];
j++;
}
}
System.out.println("------------------------------------------");
System.out.println("\nAvailable fruits after delete : " + newFruits.length + "\n");
// print the final output
for (String s : newFruits) {
System.out.println(s + " is Available\n");
}
}
public static void main(String args[]) {
new DeleteValue().delete("mango");
;
}
}
Explanation :
The only Issue I am having its that Fruit Array is not decreasing the
size
An array is a container object that holds a fixed number of values of a single type. The length of an array is established when the array is created. After creation, its length is fixed
So what we can do is either use a dynamic array or we can use a work around like the above code:
If you want to "grow" or "shrink" an existing array, you have to allocate a new array of the appropriate size and copy the array elements from old array to the new array.
In the above code I have provided comments for the working steps.
We are solving this problem is three steps:
Find and delete the fruit item from array.
count the deleted values from old array so that we can create a new array
of that size.
Move all remaining items from old array to new array.
I have to compare two String arrays with integer values separated by "#" input by the user as follows:
Input 1: Size of the array:
3
Input 2: (Array 1)
1#4#5
3#6#7
5#8#9
Input 2: (Array 2)
1#3#5
4#6#7
5#7#9
They contain the same no. of integer strings per line as specified by the user input array size. For eg: the 1st line of Array 1 = 1#4#5 = 3 integer strings.
In case, the array inputs are blank in any line, the output should be "invalid".
The output should be "yes" if the integer values in both the arrays are same irrespective of their position in the array i.e. if they are equivalent, otherwise the output should be "no".
My code passes very few test cases and mostly gives the correct output only when the two arrays are transpose of each other (when seen from the input format). It does not give the correct output when all the integer strings in both the arrays are same irrespective of their positions in the array.
eg. 1: Test case passed:
The output for the arrays in the example above is yes
eg.2: Test case failed:
Input 1: Size of the array:
2
Input 2: (Array 1)
1#6
3#4
Input 2: (Array 2)
6#3
4#1
Output: no
Here is my code:
import java.util.Scanner;
import java.util.Arrays;
public class StringComparison
{
public static void main (String[]args)
{
Scanner input = new Scanner (System.in);
// Input the array size
System.out.println("Enter the array size:");
int size = input.nextInt();
input.nextLine();
String[] s1 = new String[size];
String[] s2 = new String[size];
// Input 1st array elements
System.out.println("Enter the 1st array elements:");
for (int i=0;i<size; i++)
{
s1[i]= input.nextLine();
}
// Input 2nd array elements
System.out.println("Enter the 2nd array elements:");
for (int i=0;i<size; i++)
{
s2[i]= input.nextLine();
}
// Check for equivalence
System.out.println(equivalent (size, s1, s2));
}
public static String equivalent (int input1, String[]input2, String[]input3)
{
String result =null;
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
char []b1 = new char[input1*input1];
char[]b2 = new char[input1*input1];
int[] num1 = new int[input1*input1];
int[] num2 = new int[input1*input1];
for (int i=0; i<input1;i++)
{
String[] a1 = input2[i].split("#");
// if the user inputs are less or more than required
try
{
for (int j=0;j<input1;j++)
sb1.append (a1[j]);
}
catch (java.lang.ArrayIndexOutOfBoundsException e)
{
result ="invalid";
return result;
}
}
for (int i=0; i<input1;i++)
{
String[] a2 = input3[i].split("#");
// if the user inputs are less or more than required
try
{
for (int k=0;k<input1;k++)
sb2.append (a2[k]);
}
catch (java.lang.ArrayIndexOutOfBoundsException e)
{
result ="invalid";
return result;
}
}
// Storing the contents of the StringBuilder objects in a char array
sb1.getChars (0,((input1*input1)-1),b1,0);
sb2.getChars (0,((input1*input1)-1),b2,0);
// Converting the elements of the char array into integers and storing it in an int array
for (int p=0; p<((input1*input1)-1);p++)
{
num1[p] = Character.digit( b1[p],(input1*input1)-1);
}
// Converting the elements of the char array into integers and storing it in an int array
for (int q=0; q<((input1*input1)-1);q++)
{
num2[q] = Character.digit( b2[q],(input1*input1)-1);
}
// Sorting the two integer arrays
Arrays.sort (num1);
Arrays.sort (num2);
if (Arrays.equals (num1,num2))
{
result = "yes";
}
else
{
result ="no";
}
return result;
}
}
i have rewritten your equivalent method. i hope its okay to use ArrayList.
private static String equivalent(String[] s1, String[] s2) {
ArrayList<Integer> num1 = new ArrayList<Integer>();
ArrayList<Integer> num2 = new ArrayList<Integer>();
for (String str : s1) {
String[] storage = str.split("#");
for (String st : storage) {
num1.add(Integer.parseInt(String.valueOf(st)));
}
}
for (String str : s2) {
String[] storage = str.split("#");
for (String st : storage) {
num2.add(Integer.parseInt(String.valueOf(st)));
}
}
Collections.sort(num1);
Collections.sort(num2);
if (num1.equals(num2)) {
return "yes";
} else {
return "no";
}
}
this does what you want to achieve with fewer code. if you need help understand or have any other questions feel free to ask
The logic you are using to make the integer array is wrong and it produced invalid entries.Try printing the array values.All the test cases will fail.
Try below to convert the the char into the integer
num2[q] = Integer.parseInt(String.valueOf(b2[q]));
num1[p] = Integer.parseInt(String.valueOf(b1[p]));
Note:Example 1 should have been "NO". There is no 8 in the second input.
I already have the following code
public class Qn3
{
static BigDecimal[] accbal= new BigDecimal[20];
private static Integer[] accnums = new Integer[5];
public static void main(String[] args)
{
int count;
accnums = {1,2} //i cant add this line of code as well, what is wrong?
while(accnums.length < 5)
{
count = accnums.number_of_filled_up_indexes
//this is not actual code i know
//do this as the number of values in the array are less than 5
break;
}
//do this as number of values in the array are more than 5
}
}
I must use this code there is no changing this is a requirment, so please dont suggest to use arraylist and such (i am aware of other array types and methods)
The problem is that as I have already declared that accnums must contain only 5 values, that is predefined.
I am trying to perform a check whether the ones that are not null and if all are null. To do this I have tried this but this is giving me 5 p(pre-defined integer array value not what I want).
public static void main(String[] args)
{
int count = 0;
accnums = new Integer[] {1,2,null,null,null};
for (int index = 0; index < accnums.length; index++)
{
if(accnums[index] != null)
{
count++;
}
}
System.out.println("You have used " + count + " slots);
}
Try this...
accnums[0] = new Integer(1);
accnums[1] = new Integer(2);
Both the below will work if done during Declaration and Initializing time of and array.
Integer[] arr = new Integer[]{1,2,3};
Integer[] arr = {1,2,3}
But when you just declare the array as
Integer[] arr = new Integer[3]; // Still array holds no Object Reference Variable
then later initialize it this way...
arr = new Integer{1,2,3,}; // At this time it hold the ORV
Array are always initialized whether used at class or method scope, so for an int array all the values will be set to default as 0, and for Integer it will be null, as its an Wrapper object.
Eg:
Integer[] arr = new Integer[5];
arr[0] = 1;
arr[1] = 2;
System.out.println(arr.length);
for (Integer i : arr){
if (i!=null){
count++;
}
}
System.out.println("Total Index with Non Null Count :"+count);
}
accnums[0] = 1;
accnums[1] = 2;
final int count = accnums.length
- Collections.frequency(Arrays.asList(accnums), null);
System.out.println("You have used " + count + " slots");
or, if you really must do it manually...
int count;
for (final Integer val : accnums) {
if (val != null) {
++count;
}
}
I have an array ordered in alphabetical order;
[0] = apple
[1] = banana
[2] = mango
[2] = melon
What I need to do now, Is split the string array into smaller string arrays with groups of the letters, so the output would be:
[0] = apple
[0] = banana
[0] = mango
[1] = melon
I've tried a few methods, but all of them are hopeless, Can you give me a piece of code that will do this? I promise to give the best answer a tick and all the good answers a point!
Here's how I would do :
create a sorted map (for example a TreeMap) with the first char as key, and a list of fruits as value
iterate through the original array.
at each iteration, extract the first char and see if the map contains it as a key. If not, create an empty list of fruits, and put it in the map. Put the current fruit in the list (whether it was already in the map or not)
Ask for the values of the map : it's an ordered collection of fruit lists. transforming it into an array of arrays is trivial with Collection.toArray.
Here is a simple but not thoroughly optimized example. Also I'm not sure how this will fare with multi-byte first characters as in Umlauts etc.
public static void sortByFirstChar() {
String[] array = new String[4];
array[0] = "apple";
array[1] = "banana";
array[2] = "mango";
array[3] = "melon";
HashMap<Character, ArrayList<String>> charToList = new HashMap<Character, ArrayList<String>>();
for (String item : array) {
char firstChar = item.charAt(0);
if (charToList.containsKey(firstChar)) {
charToList.get(firstChar).add(item);
} else {
ArrayList<String> list = new ArrayList<String>();
list.add(item);
charToList.put (firstChar, list);
}
}
Set<Character> keySet = charToList.keySet();
for (char key : keySet) {
// Here are the arrays
System.out.println("Items for char " + new Character((char)key).toString() + ":");
for (String item : charToList.get(key)) {
System.out.println (" " + item);
}
}
}
Sample output:
Items for char b:
banana
Items for char a:
apple
Items for char m:
mango
melon
You will definitely want to use a better way to store the data instead of arrays... maybe a TreeMap or just a List of strings:
String[] arr = new String[]{"apple", "banana", "mango", "melon"};
List<List<String>> arrs = new ArrayList<List<String>>();
char f = 0;
List<String> last = null;
for(String s : arr){
if( f != s.charAt(0) ){
f = s.charAt(0);
// since first the char is different, create a new array
last = new ArrayList<String>();
last.add(s);
if( last != null ){
arrs.add(last);
}
}
else {
last.add(s);
}
}
In the case above, you will have a List of Lists of strings (arrs). Good thing about lists is that their size is dynamic (arrays dimensions are static).
Here's an UNOPTIMIZED solution. I tested for a few different combos. The output is list of arrays. The printList function prints the array in logCat you might want to replace it with your own function:
public class SortArray extends Activity {
ArrayList matchedFruits = new ArrayList();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String fruits[] = new String[7];//Sorted array
fruits[0] = "apple";
fruits[1] = "apricot";
fruits[2] = "banana";
fruits[3] = "mango";
fruits[4] = "melon";
fruits[5] = "pineapple";
fruits[6] = "peach";
char currChar=fruits[0].charAt(0);//Get first char of first element
boolean match=false;
int len=fruits.length;
List tmp = new ArrayList();
for(int i=1;i < len;i++)
{
Log.d("Comparing ", fruits[i].charAt(0)+","+currChar);
if (fruits[i].charAt(0)==currChar)
{
if (match==false)//new match?
{
match=true;//Reset search
tmp.clear();//clear existing items
tmp.add(fruits[i-1]);
Log.d("Started new list ", fruits[i-1]);
}
else
{
tmp.add(fruits[i-1]);
Log.d("Added to list ", fruits[i-1]);
}
}
else
{
match=false;
tmp.add(fruits[i-1]);
matchedFruits.add(tmp.toArray(new String[tmp.size()]));//add to final list
Log.d("Finished a list ", fruits[i-1]);
tmp.clear();//clear existing items
}
currChar=fruits[i].charAt(0);
}
tmp.add(fruits[len-1]);
matchedFruits.add(tmp.toArray(new String[tmp.size()]));//add left over items
printList();
}
void printList()
{
//Print the list
for(int i=0;i < matchedFruits.size();i++)
{
String tmp2[]= matchedFruits.get(i);
for (int j=0;j < tmp2.length;j++)
{
Log.d("Final list", "Array #"+i+"["+j+"],"+tmp2[j]);
}
}
}
}