I have four arrays of strings and I would like to create a two dimensional array of 3 columns and dynamic rows.
the arrays are like:
String[] first_name;
String[] last_name;
String[] unit;
String[] phone_number;
Object[][] obj = new Object[first_name.length()][3]
My problem is how do I achieve something like this:
obj = {first_name[index] + " " + last_name[index], unit[index], phone_number[index]}
Please help out!!!
I am assuming that by dynamic rows you mean that it depends on the number of elements in the first_name array.
So you could simply iterate:
String[][]obj = new String[first_name.length][3];
for (int i = 0; i < first_name.length; i++)
{
obj[i][0] = first_name[i] + " " + last_name[i];
obj[i][1] = unit[i];
obj[i][2] = phone_number[i];
}
However, this approach is not very good. You should consider creating an object for example named Employee which as the 3 fields, and then you just have an array of Employee
For example:
public class Employee
{
String name;
String unit;
String phoneNumber;
public Employee(String name, String unit, String phoneNumber)
{
//... rest of constructor to copy the fields
}
//... setters and getters
}
And then you just have:
Employee[] employees = new Employee[first_name.length];
for (int i = 0; i < first_name.length; i++)
{
employees[i] = new Employee(first_name[i] + " " + last_name[i], unit[i], phone_number[i]);
}
Would this help?
int len = first_name.lenghth();
String[][] arr2d = new String[len][3];
for (int i=0; i < len; i++) {
arr2d[i][0] = first_name[i] + " " + last_name[i];
arr2d[i][1] = unit[i];
arr2d[i][2] = phone_number[i];
}
this could be what you are looking for: (Assume that the four arrays have same length)
String[][] result = new String[first_name.length][3];
for(int i =0; i<first_name.length;i++){
result[i][0]=first_name[i]+" "+last_name[i];
result[i][1]=unit[i];
result[i][2]=phone_number[i];
}
String[] first_name = new String[length];
String[] last_name = new String[length];//length means your length of string
String[] unit = new String[length];
String[] phone_number = new String[length];
Object[][] obj = new Object[first_name.length][3];
for(int index =0;index<first_name.length;index++){
obj[index][0] = first_name[index] + " " + last_name[index];
obj[index][1] = unit[index];
obj[index][2] = phone_number[index];
}
There are a couple of ways to make 3-D arrays.
I would avoid Object[][], I never like the handling or performance.
Since a 3-D array is just an array of arrays, an easy approach would to use the List data structure.
List[] or List> should do the trick. This way you have all the built-ins of a Collection object plus you can also Apache commons, lambdaJ or Guava on top of it.
If you are dead set on using primitive arrays then you could also make a regular 2-D array, [], that can act like a 3-D array, [][].
Here is simple wrapper method I made around a basic array that will function the same as 3-D array.
public class MyThreeDArray{
int MAX_ROW;
int MAX_COL;
int[] arr;
public MyThreeDArray(final int MAX_ROW, final int MAX_COL){
this.MAX_ROW = MAX_ROW;
this.MAX_COL = MAX_COL;
arr = new int[MAX_ROW * MAX_COL];
}
private int findIndex(int row, int col) throws IllegalArgumentException{
if(row < 0 && row >= MAX_ROW ){
throw new IllegalArgumentException("Invaild row value");
}
if(col < 0 && col >= MAX_COL ){
throw new IllegalArgumentException("Invaild col value");
}
return ( row * MAX_COL + col );
}
public int get(int row, int col){
return arr[findIndex(row, col)];
}
public void set(int row, int col, int value){
arr[findIndex(row, col)] = value;
}
}
Also keep in mind I never tested any of this.
So if you did this with Strings then row 0 might contain the first name values, ... and row 4 could have the unit values.
To retrieve person A's data with this wrapper could make a call similar to this:
String firstName = myWrapper.get(0,0);
String lastName = myWrapper.get(0,1);
String phone = myWrapper.get(0,2);
String unit = myWrapper.get(0,3);
And person B's data would be stored in the second row.
But why try to combine arrays together? You could easy make a POJO called person
public class Person{
String firstName;
String lastName;
String phone;
String unit;
public Person(){}
//ToDo: Getters and Setters
}
This way could just easily add validation and clearly call a specific person without any trouble.
Person[] customers = new Person[5];
or better yet
List<Person> customers = new ArrayList<Person>();
You could create a List of 1D arrays: List<String []> arrayList = new ...
Then you can do arrayList.add(first_name);
Related
I have an object array containing two fields per object.
I have to write a method that will sort my array by the first field.
I already have a method which extracts the first field from each object
I always get an error message when I call my method to sort.
Here is my code:
public static void trier(String[]code, String[]nom, int nbObj) {
for(int i = 0; i < nbObj-1; i++) {
int indMin = i;
for (int j = i+1; j < nbObj; j++)
if (code[j].compareTo(code[indMin]) < 0)
indMin = j;
if (indMin != i) {
// permutation :
String tempo = code[i];
code[i] = code[indMin];
code[indMin] = tempo;
// permutation :
String temp = nom[i];
nom[i] = nom[indMin];
nom[indMin] = temp;
}
}
}
and the call :
Classe.trier(tableau, tableau, nbObj);
I also tried Class.sort(array.getCode(), array.getName(), nbStudent);
But I still have compilation errors
thank you in advance for your help
First of all, you don't have to use 2 separate arrays to contain your data. You can put everything in a single array, but better way is to use Java Collections. Perfect choice is ArrayList. However, you still better combine two fields into a single object. You can do it like this:
public class MyObject {
String code;
String nom;
MyObject(String code, String nom) {
this.code = code;
this.nom = nom;
}
}
Now you have a class containing 2 fields. Your aim is to sort a collection of such objects by their second field (nom). You can do this easily since Java 8:
public static void sort1(ArrayList<MyObject> list) {
list.sort((obj1, obj2) -> obj1.nom.compareTo(obj2.nom));
}
Or
public static void sort2(ArrayList<MyObject> list) {
list.sort(Comparator.comparing(MyObject::getNom));
} // However for this you need to add method getNom to MyObject
Remember to put your objects in the collection properly.
For example:
MyObject a = new MyObject("abc", "abide");
MyObject b = new MyObject("cab", "whatever you want");
ArrayList<MyObject> list = new ArrayList<>();
list.add(a);
list.add(b);
trier(list);
I'm trying to create a FileIO where random numbers are placed into a .txt file and outputted, sorted in another .txt file. I have a bubble sort code that can sort numbers & I have another code that makes a .txt file. I'm just not sure how I'd implement these 2 together.
Here's my fileIO code:
public static void main(String[] args) {
File file = new File("test.txt");
//Writes name and age to the file
try {
PrintWriter output = new PrintWriter(file);
output.println("Rober");
output.println(27);
output.close();
} catch (IOException ex) {
System.out.printf("ERROR: %s\n", ex);
}
//Reads from the file
try {
Scanner input = new Scanner(file);
String name = input.nextLine();
int age = input.nextInt();
System.out.printf("Name: %s Age %d\n", name, age);
} catch (FileNotFoundException ex) {
System.out.printf("ERROR: %s\n", ex);
}
}
And here is my bubble sort code:
public static void main(String[] args) {
Random num = new Random();
//Creating an array for 10 integers
int [] number = new int [10];
System.out.print("Random Numbers:");
/*Display the unsorted numbers in a random order.
These numbers range from 0 to 100
*/
for (int d = 0 ; d<number.length ; d++){
/* We add a "+1" to the nextInt(100) here because then the numbers
will only range from 0 to 99.
*/
int RandomG = num.nextInt(100)+1;
number[d] = RandomG;
System.out.print(" " +RandomG);
}
//Display the sorted numbers
System.out.print("\nSorted Numbers:"+Arrays.toString(BubbleSortAsceMethod(number)));
}
public static int [] BubbleSortAsceMethod(int[] number){
int placeholder;
for(int i = 0 ; i < number.length-1 ; i++){
for ( int x = 1 ; x < number.length-i ; x++){
/*If the first number in the sequence is greater than the second
number, than save the first number of sequence in placeholder
and place the second number in the first numbers position, and
put the placeholder in the second numbers position (SWAP).
*/
/*
Since this is saying that when the first term is bigger than the
2nd term, the sequence will increase. If we flip the relational
operator, the sequence will decrease.
*/
if ( number[x-1] < number[x]){
placeholder = number[x-1];
number[x-1] = number[x];
number[x] = placeholder;
}
}
}
return number;
}
I'm kinda new to all this java stuff so please go a bit easy on me! Any help at all is appreciated :)
As the data contained in the file will consist of a pair of values: The name (String) and the age (int), you will need to retain their relationship. The best way of doing this would be to create a Class to represent the data. Eventually you want to sort the data on age using your BubbleSort method. While practically this would not be your first choice to sort data, I assume that this is a requirement. The BubbleSort method you have sorts an int[] by comparing each entry against it's immediate neighbor. With int being primitive, you can directly compare each element using the < operator.
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.age = age;
this.name = name;
}
public String getName() { return name; }
public int getAge() { return age; }
#Override
public String toString() {
return name + System.lineSeperator() + age;
}
#Override
public int compareTo(Person person) {
return this.age - person.age;
}
}
You may want to implement the Comparable interface to compare Objects; in which the interface must be implemented by Overriding the compareTo(Person person) method. You can impose sorting on age by returning the difference in age. This is not the only way you can impose the order you want; you may wish to compare directly using the getAge() of each Object or create a Comparator object.
Using the Comparable interface does allow you to make your BubbleSort class more generic, however (though the array must be of Objects that implement the interface; hence no primitive types).
public class BubbleSort {
public static <T extends Comparable> T[] BubbleSortAsceMethod(T[] array) {
for (int i = 0; i < array.length - 1; i++) {
for (int x = 1; x < array.length - i; x++) {
if (comparator.compare(array[x - 1], array[x]) < 0) {
T placeholder = array[x - 1];
array[x - 1] = array[x];
array[x] = placeholder;
}
}
}
return array;
}
}
You will notice that this sort method has some slight differences from your original, namely the BubbleSortAsceMethod method signature with the introduction of generic type parameters. Once again, this is completely optional, though this does give you the flexibility to use this method in the future for other arrays of Classes that extend the Comparable interface.
If you don't want to use generics or the Comparable interface, you will need to change the method signature and if statement.
You're method signature should instead look like public static Person[] BubbleSortAsceMethod(Person[] array) and the if statement if (array[x-1].getAge() < array[x].getAge())
This can give you an illustration of it working, though this does not consider the file io which should be simple to implement from what you have done already.
static Random random = new Random();
public static void main (String args[]) {
int size = 100;
Person[] peopleArray = new Person[size];
for (int i = 0; i < size; i++) {
String name = generateName(random.nextInt(4) + 4);
int age = random.nextInt(100);
peopleArray[i] = new Person(name, age);
}
peopleArray = BubbleSort.BubbleSortAsceMethod(peopleArray);
}
Note that this conforms, at least as much as possible, to the code you have implemented this far. If the BubbleSort and use of arrays are not critical, data structures that implement the List interface, such as ArrayList, can allow you to implement this much cleaner. This does not use the BubbleSort method at all.
public static void main (String args[]) {
int size = 100;
ArrayList<Person> people = new ArrayList<>();
for (int i = 0; i < size; i++) {
String name = generateName(random.nextInt(4) + 4);
int age = random.nextInt(100);
people.add(new Person(name, age));
}
peopleList.sort(Person::compareTo);
//or, if you don't want to implement comparable
peopleList.sort(Comparator.comparing(Person::getAge));
}
Appendix:
Used for illustrative purposes: Generates a name of a set length (randomly).
static char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
public static String generateName(int length) {
if (length > 0) {
return alphabet[random.nextInt(alphabet.length)] + generateName(length - 1);
}
return "";
}
i have a situation where i have to read xml files where i get three elements like this
2019-03-19,null,null
2016-11-30,null,null
2016-10-14,null,null
2016-09-30,null,null
2016-09-30,1,YEARS
2016-09-30,3,MONTHS
2016-09-30,4,MONTHS
I have to store all three items on some data structure and apply my logic like below
I have to find the max of last item and then for that i have to find the max of second item then for that i have to find the max of first element of more than one is present .
Please suggest me some idea
Create a single object like below that can hold all three data elements and is also capable of handling a "null" value for the quantity and term length values. You may want to have the constructor convert the String date (2019-03-19) into a real date object or you could handle that before object creation. Then add these objects to a data structure (i.e. list, etc) that you can use to manage and organize them.
public class ListElement {
public Date date;
public Integer qty;
public String termLength;
public ListElement(Date d, Integer q, String t) {
this.date = d;
this.qty = q;
this.termLength = t
}
// getter methods
public Date getDate() {
return this.date;
}
public Integer getQty() {
return this.qty;
}
public String getTermLength() {
return this.termLength;
}
public toString() {
return System.out.println(this.date + "::" +
this.qty + "::" +
this.termLength)
}
}
You can create an enum if you have some predefined terms:
enum Term {
AGES, YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS;
}
And use it in your class with other two types as:
public class MyObjects {
private Date date;
private Integer quantity;
private Term term;
public MyObjects(Date date, Integer quantity, Term term) {
this.date = date;
this.quantity = quantity;
this.term = term;
}
// getters, setters
}
Then define the constructor that accepts these 3 arguments and use it while processing XML file.
Two different ways to store the data. One is 2D array and the other is arraylist. All the data is type String. You would have to Parse the Integers using Integer.parseInt() to get int value. You will also have to catch for null values. This assumes that your xml data have newline characters at the end of each line.
public static void main(String[] args) {
// TODO code application logic here
//Assuming there are \n char at end of line
String xml = "2019-03-19,null,null\n" +
"2016-11-30,null,null\n" +
"2016-10-14,null,null\n" +
"2016-09-30,null,null\n" +
"2016-09-30,1,YEARS\n" +
"2016-09-30,3,MONTHS\n" +
"2016-09-30,4,MONTHS";
System.out.println("2D Array Output:");
String[][] twoDArrayExample = twoDArrayVersion(xml);
//print 2D array
for(int i = 0; i < twoDArrayExample.length; i++)
{
for(int z = 0; z < twoDArrayExample[i].length; z++)
{
System.out.print(twoDArrayExample[i][z] + " - ");
}
System.out.println();
}
System.out.println("\n\nArray List Output:");
ArrayList<ArrayList<String>> arrayListExample = arrayListVersion(xml);
//print arraylist
for(ArrayList<String> entry : arrayListExample)
{
for(String item : entry)
{
System.out.print(item + " + ");
}
System.out.println();
}
}//end of main
static String[][] twoDArrayVersion(String xml)
{
String[][] dataHolder;
String[] tempDataHolder = xml.split("\n");
dataHolder = new String[tempDataHolder.length][3];
for(int i = 0; i < tempDataHolder.length; i++)
{
String[] tempDataHolder2 = tempDataHolder[i].split(",");
dataHolder[i][0] = tempDataHolder2[0];
dataHolder[i][1] = tempDataHolder2[1];
dataHolder[i][2] = tempDataHolder2[2];
}
return dataHolder;
}
static ArrayList<ArrayList<String>> arrayListVersion(String xml)
{
ArrayList<ArrayList<String>> dataHolder = new ArrayList();
String[] tempDataHolder = xml.split("\n");
for(int i = 0; i < tempDataHolder.length; i++)
{
ArrayList<String> tempArrayList = new ArrayList();
String[] tempDataHolder2 = tempDataHolder[i].split(",");
tempArrayList.add(tempDataHolder2[0]);
tempArrayList.add(tempDataHolder2[1]);
tempArrayList.add(tempDataHolder2[2]);
dataHolder.add(tempArrayList);
}
return dataHolder;
}
how do you sort group of arrays that are paired to each other?
for example is that if you have an array of student numbers and student names. how can i make student names adjust too. when you sort it by student number?
example output of what i wanted to be:
unsorted:
ID numbers name course
5 jomar IT
3 karen CS
sorted (by ID numbers)
ID numbers name course
3 karen CS
5 jomar IT
I've tried to use TreeMap but there's this problem that if the value of ID numbers are the same, it will overwrite the other and it will print like this:
sorted (by ID numbers)
ID numbers name course
3 karen CS
in reply to Stultuske
i tried to use 1 array that contains id num, name, course.
its like this:
for(int i=0;i<array.length;i++){
String [][] storeAllArray = {{array[i]},{array2[i]},{array3[i]}};
System.out.println(storeAllArray[0][0] + " "
+ storeAllArray[1][0] + " "
+ storeAllArray[2][0]);
}
public class Student implements Comparable {
private int id;
private String name;
private String course;
public Student(int pid, int pname, int pcourse) {
id = pid;
name = pname;
course = pcourse;
}
#Override
public int compareTo(Object o) {
return new Integer(id).compareTo(new Integer(((Student)o).getID()));
}
public int getID() { return id; }
public String getName() { return name; }
public String getCourse() { return course; }
}
At that point, you just make an ArrayList (Or whatever collection you like) of Students, and call Collections.sort(~initialized ArrayList~);
If you had a Collection<Student>, you'd sort it like this:
Collections.sort(studentList,new Comparator<Student>() {
int compareTo(Student s1, Student s2) {
return s1.getSomeField().compareTo(s2.getSomeField());
)
});
Basically you pass a Comparator (generated inline here) to Collections.sort()
I'd highly recommend against the parallel array version since it's really avoiding the OO nature of Java.
But if you REALLY want to do it, you'd have to have a third array that is just the indexes from 1 to number of elements in your array, then you'd have to use a parallel index array and sort it using Arrays.sort() with a Comparator that compares your parallel array's values (instead of the index array) and then you iterator over the sorted index array and print out the elements that match the index of the other array... Really much easier to do it correctly as above.
Part 1: Define your Comparator as following:
public class MyComparator implements Comparator<Object[]> {
#Override
public int compare( Object[] o1, Object[] o2 ) {
if ( (int) o1[0] > (int) o2[0] )
return 1;
else if ( !((int) o1[0] > (int) o2[0]) )
return -1;
else
return 0;
}
}
Part 2: And then follow my example code below in your main class:
public class MyComparatorTest {
public static void main( String[] args ) {
List<Object[]> list = new ArrayList<Object[]>();
Object[] o = new Object[3];
o[0] = 2;
o[1] = "TWO";
o[2] = "RR";
list.add(o);
o = new Object[3];
o[0] = 3;
o[1] = "THREE";
o[2] = "GG";
list.add(o);
o = new Object[3];
o[0] = 1;
o[1] = "ONE";
o[2] = "TT";
list.add(o);
// This sorts your list
Collections.sort(list, new MyComparator());
// The following loop is only to show you the sorted list content.
for (Object[] obj : list) {
for (Object obj2 : obj) {
System.out.print(" " + obj2);
}
System.out.println();
}
}
}
Sample output is:
1 ONE TT
2 TWO RR
3 THREE GG
I have an arrayList which contains Objects. Each object contains a number of strings. I am trying to take these strings and add them to a two dimensional array.
public void iterateRow(Row row)
{
int x = 0;
int y = size();
tableArray = new String[y][5];
while(x < y){
int z = 0;
for (String s: row.rowString()){
tableArray[x][z] = s;
z++;
}
x++;
}
}
Whenever i run and create a new instance for the row class the method should add the strings contained in Row to the array. However it duplicates the latest entry x times (where x is the total number of entries).
Here is the Row class for further reference:
public class Row
{
public String appNumber;
public String name;
public String date;
public String fileLoc;
public String country;
public String elementString;
public String results[];
public Row(String appNumber, String name, String date, String fileLoc, String country, Table table)
{
this.appNumber = appNumber;
this.name = name;
this.date = date;
this.fileLoc = fileLoc;
this.country = country;
table.addApplicant(this);
}
public String[] rowString()
{
String[] a = {appNumber, name, date, fileLoc, country};
return a;
}}
I think it is a silly logical error in the iterateRow() method but i can't seem to work out what. Any help would be appreciated.
Edit: After everybody's help i have removed the while loop. However it still seems to be duplicating the Row rather than moving onto the next?
public void iterateRow(Row row)
{ int x = 0;
int y = size();
tableArray = new String[y][row.rowString().length];
for(int i =0; i<y;i++){
int z = 0;
for (String s: row.rowString()){
tableArray[x][z] = s;
z++;
}x++;}
}
The problem looks like it is in the while loop. If size() returns 3, for example, then the while loop will execute with x=0,1,2 so you'll assign tableArray[0], then tableArray[1] and then tableArray[2].
Its hard to tell what the solution is as I can't understand why you've got the while loop in the code at all.
It looks like you want to iterate through each element of a List of Rows
Maybe you want to use a method similar to the following:
public void iterateRows(List<Row> rows) {
int cols = 5;
int row = 0, col = 0;
tableArray = new String[rows.size()][cols];
for(Row row : rows) {
col = 0;
for(String c : row.rowString()) {
tableArray[row][col] = c;
col++;
}
row++:
}
}
However, it would be good to implement your own error checking incase there are more than 5 columns...
EDIT
This is probably not the best design to use for your program, and I would recommend changing it so that when a new row is added, you don't have to iterate through each of the old rows as well.
Your iterateRow method re-creates tableArray each time it is called. Because of the while loop, your Row object gets replicated y times in the array.
I suspect that you want to create your array outside of the iterateRow method and not use a while loop (just the for loop) to populate the next slot in your array.
You are not taking care to size the two dimensional array relative to the size of the Row.
While this might not be the smoking gun, it would be far safer to do
tableArray = new String[y][row.rowString().length];
instead of
tableArray = new String[y][5];
I don't know if this is for practical purpose or how IterateRow() is called, but a logical way to get this working would be to declare the array first, add 2 argument in IterateRow(reference of the array and currentRow). Then, inside iterateRow you get rid of the while loop and you just loop for the string proprieties.