Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 7 of 7

Thread: Sorting a Multi-Dimensional String array

  1. #1
    Junior Member
    Join Date
    Mar 2021
    Location
    Ontario, Canada
    Posts
    27
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Default Sorting a Multi-Dimensional String array

    Good evening everyone,

    I am currently just a student of Java and am stuck on one part of my assignment. I have a multi-dimension array created from a CSV file. I can get it to print no problem however I need to sort it first according to a specific column.
    The array looks like this;

    Date------------Open----High----Low-----Close---AdjClose---Volume
    2000-09-01___33.05__33.45__32.75__33.38__33.38____45869
    2000-09-05___33.95__33.99__33.42__33.80__33.80____55722

    there is a lot more but did not want to type them all,

    I need to sort this array according to the 'Close' column going from highest to lowest.

    I did try a bubble sort (rookie move I know), but all it did was change the values in the Close column from high to low, the rest of the rows remained in place.

    Can anyone send a suggestion or send a sample to help me past this problem. Keep in mind that ALL fields are Strings.

    I also tried the following:

    I created two methods that separate the original array and created two more arrays, one is a Date[] and stores just the first column in a date format and the second array is a float[][] which stores the remaining values as floats.
    The float[][] array I can sort using the following,
        public void sortDataArray(float[][] arr, int colNum) {
     
            Arrays.sort(arr, new Comparator<float[]>() {
     
                @Override
                public int compare(float[] val1, float[] val2) {
     
                    if (val1[columnSort] < val2[columnSort]) {
                        return 1;
                    } else {
                        return -1;
                    }
                }
            });
        }
    I can print this one and all the float values arrange properly, but I do not know how to include the dates in the printout.

    I am really hoping someone out there can help me, my assignment is due soon, and this is the second last thing I need to get done.
    (last thig is to implement a lambda expression somewhere in my code but I will deal with that after I get this fixed)

    Thanks.

  2. #2
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    24,305
    Thanks
    54
    Thanked 2,635 Times in 2,585 Posts

    Default Re: Sorting a Multi-Dimensional String array

    Can you post the code that is working with the String array? There is probably a way to write a Comparator that will sort that array's contents. When columns are extracted to separate arrays the ability to sort the original String array is lost.
    If you don't understand my answer, don't ignore it, ask a question.

  3. #3
    Junior Member
    Join Date
    Mar 2021
    Location
    Ontario, Canada
    Posts
    27
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Default Re: Sorting a Multi-Dimensional String array

    Hello Norm,
    Here is the my entire project so far. I wasn't sure I understood what particular code you wanted to see, so I figure post it all.
    Some comments are in the code just as a reminder to me to do some repairs, you can ignore those.


     
    package AssignmentThree;
     
    import java.io.*;
    import java.util.Scanner;
    import java.util.StringTokenizer;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import static java.nio.file.AccessMode.*;
    import java.nio.file.Path;
    import java.nio.file.Paths;
     
    /**
     * Java Intermediate - Assignment 3
     * Working with CSV file located in C:\temp
     * @author Ken Leduc
     * @date July 26, 2021
     */
    public class ReadFiles {
        String fullPath = "C:/temp/NewCrudeOil.csv";
        File file = new File(fullPath);
        Path filePath = Paths.get(fullPath);
        Scanner scan;
        int printArea = 0;
        int rowCount;
        int columnCount = 0;
        String line = "";
        int countColumn;
        int countLine = 0;
        String[][] fileArray;    
     
        /**
         * FileCheck, looks in the file location to make sure 
         * file does exist.
         */
        public void FileCheck(){       
     
           try
            {
                filePath.getFileSystem().provider().checkAccess(filePath, READ, EXECUTE);                   
            }  
     
            catch(Exception FileNotFoundException)
            {
                System.out.println("File does not exist!");
                System.exit(-1);
            } 
        }   
     
        /**
         * RowCount, counts the total rows in the CSV file
         * Assigns that value to rowCount variable.
         */
        public int getRowCount(){
     
            try {
                BufferedReader br = new BufferedReader(new FileReader(file));
     
                while((line = br.readLine()) != null){
                    rowCount++;
                }         
     
     
            } 
            catch (FileNotFoundException ex) {
                System.out.println("Row count error.");           
                Logger.getLogger(ReadFiles.class.getName()).log(Level.SEVERE, null, ex);
            }
            catch (IOException ex) {
                System.out.println("There was an error counting the rows.");
                Logger.getLogger(ReadFiles.class.getName()).log(Level.SEVERE, null, ex);
            } 
     
            return rowCount;
        }
     
        /**
         * CSVConvert, takes the CSV file and stores all the data in a 2D array
         * Takes each token and stores them in the appropriate location in the array.
         */
        public String[][] getCSVConvert(){
            fileArray = new String[rowCount][7];       
     
            try{
                BufferedReader br = new BufferedReader(new FileReader(file));
     
                while((line = br.readLine()) != null){
     
                    StringTokenizer separator = new StringTokenizer(line, ",");
     
                        for(countColumn = 0; countColumn < 7; countColumn++){ 
                            fileArray[countLine][countColumn] = separator.nextToken(); 
                        }
                    ++countLine;
                } 
     
           }      
            catch(IOException e){
                System.out.println("CSVConvert errored, check code");
            }
     
            return fileArray;
       }
     
        /**
         * PrintArray, takes the fileArray and neatly prints out the results 
         * to the screen.
         */
        public void PrintArray(){
            System.out.println("\nCrude Oil Stock Prices.\nStarting September 2000 to December 2013.");
                printHeader();
     
            try
            {
                if(printArea == 0){
                    for(int lineCount = 0; lineCount < countLine; lineCount++){ 
                        for(int columnCount = 0; columnCount < countColumn; columnCount++){
                            System.out.printf("%-15s", fileArray[lineCount][columnCount]); 
                        }
                    System.out.println(); 
                    printArea = rowCount;
                    }
                }
                else{
                    for(int lineCount = 0; lineCount < printArea; lineCount++){ 
                        for(int columnCount = 0; columnCount < countColumn; columnCount++){
                            System.out.printf("%-15s", fileArray[lineCount][columnCount]); 
                        }
                    System.out.println();    
                    }            
                }
                System.out.println("First " + printArea + " lines were printed.");
            }
            catch(Exception e)
                {
                System.out.println("Printing error!");
                }
        }
     
        /**
         * Copies the array created in CSVConvert to  new array called newArray
         * @return newArray
         */
        public String[][] getArray(){
            String[][] newArray = fileArray;
     
            return newArray;
        }
     
        /**
         * User enters the number of rows to print.
         * @return printArea
         */
        public int getPrintArea() {
            Scanner input = new Scanner(System.in);
            System.out.print("Enter the number of rows to print or enter 0 for all rows. -> ");
     
        try{  
            int number = input.nextInt();
            if(number > countLine){
                    System.out.println("You selected a number that exceeds the total number of rows\n"
                                        + "Please try a new number.\n");
                    getPrintArea();                
            }
            else if(number<0){
                    System.out.println("Please enter a whole number.\n");
                    getPrintArea();
            }
     
            else      
            {        
                    printArea = number;
            }   
        }
        catch(Exception e){
            System.out.println("You entered an incorrect number, please try again.\n");
            getPrintArea();        
        }    
            System.out.println();
            return printArea;
        }
     
        /**
         * Prints and formats the header for all the displayed data
         */
        public void printHeader(){
            System.out.printf("%-14s %-14s %-14s %-14s %-14s %-14s %-14s", "Date", "Open", "High", "Low", "Close", "Adj Close", "Volume");
            System.out.println(); 
        }
    }


    This is the class that I need to insert the sorting method into,

    package AssignmentThree;
     
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.Date;
     
    public class Calculations extends ReadFiles {
     
        ReadFiles readFiles = new ReadFiles();
        int countingRows = readFiles.getRowCount();
        int innerCount = 0;
        int outerCount = 0;
        int columnSort = 4; // column in the array to base the sort on
        String dataLine = "";
        String[][] newArray = readFiles.getCSVConvert();
        String[] dateArray = new String[countingRows];
        float[][] dataArrayValues;
        float[][] dataArrayAll;
        float highOpening;
        float highClosing;
        float lowOpening;
        float lowClosing;
        Date[] dayArray;
        Date highOpeningDate;
        Date highClosingDate;
        Date lowOpeningDate;
        Date lowClosingDate;
     
        /**
         * Calculations constructor
         */
        public void Calculations() {
            getCreateDateArray();
            getCreateDataArray();
        }
     
        /**
         * Creates a 2D array of the data only, no dates
         */
        public float[][] getCreateDataArray() {
     
            int countLine1 = 0;
            dataArrayValues = new float[countingRows][6];
            dataArrayAll = new float[countingRows][7];
     
            // creates an array of only the data
            try {
                BufferedReader reader = new BufferedReader(new FileReader(file));
     
                while ((dataLine = reader.readLine()) != null) {
     
                    for (int countColumn1 = 0; countColumn1 < 6; countColumn1++) {
                        dataArrayValues[countLine1][countColumn1] = Float.valueOf(newArray[countLine1][countColumn1 + 1]);
                    }
                    ++countLine1;
                }
     
            } catch (IOException e) {
                System.out.println("CSVConvert errored, check code");
            }
     
            return dataArrayValues;
        }
     
        /**
         * Prints the data Array list
         *
         * @param input
         */
        public void printDataArray(float[][] input) {
     
            System.out.println("\nThe list of data within the CSV file.\n");
            System.out.printf("%-14s %-14s %-14s %-14s %-14s %-14s", "Open", "High", "Low", "Close", "Adj Close", "Volume");
            System.out.println("");
     
            for (int lineCount2 = 0; lineCount2 < countingRows; lineCount2++) {
                for (int columnCount2 = 0; columnCount2 < 6; columnCount2++) {
                    System.out.printf("%-15s", dataArrayValues[lineCount2][columnCount2]);
                }
                System.out.println();
            }
        }
     
        /**
         * Creates an 1D array of all the dates
         */
        public Date[] getCreateDateArray() {
     
            SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yy");
            dayArray = new Date[countingRows];
     
            try {
                BufferedReader reader = new BufferedReader(new FileReader(file));
     
                while ((line = reader.readLine()) != null) {
     
                    try {
                        dayArray[innerCount] = sdf.parse(newArray[innerCount][0]);
                        innerCount++;
                    } catch (Exception e) {
                    }
     
                }
            } catch (IOException e) {
                System.out.println("CSVConvert errored, check code");
                System.exit(-1);
            }
     
            //printDateArray(dayArray);
            return dayArray;
        }
     
        /**
         * Prints the 1D DateArray list
         *
         * @param input
         */
        public void printDateArray(Date[] input) {
            System.out.println("\nThe list of dates within the CSV file.\n");
            for (int innerCount = 0; innerCount < countingRows; innerCount++) {
                System.out.println(input[innerCount]);
            }
     
        }
     
        /**
         * Calculates some basic values
         */
        public void basicCalcs() {
            highOpening = dataArrayValues[0][0];
            highClosing = dataArrayValues[0][3];
            lowOpening = dataArrayValues[0][0];
            lowClosing = dataArrayValues[0][3];
     
            for (int highLowSearch = 0; highLowSearch < countingRows; highLowSearch++) {
                //highest and lowest value in the Open column
                if (dataArrayValues[highLowSearch][0] > highOpening) {
                    highOpening = dataArrayValues[highLowSearch][0];
                    highOpeningDate = dayArray[highLowSearch];
                }
                if (dataArrayValues[highLowSearch][0] < lowOpening) {
                    lowOpening = dataArrayValues[highLowSearch][0];
                    lowOpeningDate = dayArray[highLowSearch];
                }
     
                //highest and lowest value in the Close column
                if (dataArrayValues[highLowSearch][3] > highClosing) {
                    highClosing = dataArrayValues[highLowSearch][3];
                    highClosingDate = dayArray[highLowSearch];
                }
                if (dataArrayValues[highLowSearch][3] < lowClosing) {
                    lowClosing = dataArrayValues[highLowSearch][3];
                    lowClosingDate = dayArray[highLowSearch];
                }
            }
     
            //the dates are print 'null', may have something to to with the date format above
            System.out.println("\nHigh/Low Stats\n");
            System.out.println("Highest opening value is " + highOpening + ", on " + highOpeningDate);
            System.out.println("Highest closing value is " + highClosing + ", on " + highClosingDate);
            System.out.println("Lowest opening value is " + lowOpening + ", on " + lowOpeningDate);
            System.out.println("Lowest closing value is " + lowClosing + ", on " + lowClosingDate);
        }
     
        /**
         * Sorts the float[][] without the date column
         * @param arr
         * @param colNum 
         */
        public void sortDataArray(float[][] arr, int colNum) {
     
            Arrays.sort(arr, new Comparator<float[]>() {
     
                @Override
                public int compare(float[] val1, float[] val2) {
     
                    if (val1[columnSort] < val2[columnSort]) {
                        return 1;
                    } else {
                        return -1;
                    }
                }
            });
        }  
     
        /**
         * This method only sorts the 'close' column not the entire rows
         */
        public void printSortedArray() {
            System.out.println("\n\tTop 10 based on their closing values.");
            printHeader();
            for (int row = 0; row < 10; row++) {
                System.out.printf("%-15s", newArray[row][0]);
     
                for (int column = 0; column < dataArrayValues[0].length; column++) {
                    System.out.printf("%-15s", dataArrayValues[row][column]);
                }
                System.out.println();
            }
        }
     
    }

    This is the last class that I need to have in my assignment,

    package AssignmentThree;
     
    import java.util.Scanner;
     
    public class DataAnalyzer extends Calculations {       
            ReadFiles readFiles = new ReadFiles();
            Calculations calc = new Calculations();
     
        /**
         * Main method calls each method,
         * with a screen printout of its status.
         * @param args 
         */
        public static void main(String[] args) {        
            DataAnalyzer newFile = new DataAnalyzer();
            newFile.FileVerification();
            newFile.CountRows();
            newFile.FileConvert();
            newFile.Printing();
     
     
        }
     
        /**
         * FileVerification, ensures a file is there and accessible
         */
        public void FileVerification(){
            try{
                readFiles.FileCheck();
                System.out.print("File exists..... ");
            }
            catch(Exception e){
                System.out.println("File does not exist!");
                System.exit(-1);
            }        
        }
     
        /**
         * CountRows, runs the method in the ReadFiles class and prints the total rows
         */
        public void CountRows(){ 
            try{
     
                System.out.println("Total number of rows = " + readFiles.getRowCount());
     
            }
            catch(Exception e){
     
                System.exit(-1);
            } 
        }
     
        /**
         * FileConvert, runs the CSVConvert method in the ReadFiles class
         * Displays, appropriate message based on the outcome.
         */
        public void FileConvert(){
     
            try{
                readFiles.getCSVConvert();
                System.out.println("CSV successfully converted to an array.");
            }
            catch(Exception e){
                System.out.println("CSVConvert errored, check code");
            }
        }
     
        /**
         * Printing, runs the print methods from the ReadFiles and Calculations classes.
         */
        public void Printing(){
                readFiles.getPrintArea();
                readFiles.PrintArray();
     
     
                Scanner inputValue = new Scanner(System.in);
     
                // printing all the dates
                System.out.print("\nWould you like to print all the dates in the CSV file? y/n -> ");
                String printDates = inputValue.nextLine();
     
                if(printDates.equals("y")){
                    getCreateDateArray();
                    printDateArray(dayArray);
                }
     
                // printing the data
                System.out.print("\nWould you like to print all the data in the CSV file? y/n -> ");
                String printData = inputValue.nextLine();
     
                if(printData.equals("y")){
                    getCreateDataArray();
                    printDataArray(dataArrayValues);
                }
     
                // printing the High/Low stats
                System.out.print("\nWould you like to print the high and low stats from the CSV file? y/n -> ");
                String basicData = inputValue.nextLine();
     
                if(basicData.equals("y")){
                    getCreateDateArray();
                    getCreateDataArray();
                    basicCalcs();
                }
     
                // printing the top ten stats
                System.out.print("\nWould you like to print the top ten stats from the CSV file? y/n -> ");
                String topTenData = inputValue.nextLine();
     
                if(topTenData.equals("y")){
     
                    sortDataArray(dataArrayValues, columnSort);
                    printSortedArray();
                }
     
                calc.Calculations();
        }
    }

    I really hope you can help me with this,

  4. #4
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    24,305
    Thanks
    54
    Thanked 2,635 Times in 2,585 Posts

    Default Re: Sorting a Multi-Dimensional String array

    I don't think I need the full code to be able to work on sorting an array.
    If the data is in an array where you want the contents of the array to be sorted based on what is in a field in a row, then a Comparator should be able to do it.
    Do you have code that builds an array with the data to be sorted?
    Each row in the array can be an array with the fields for the row.
    What field in the record should be used to control the sorting?

    Note: The use of extends for the posted code does not make sense.
    How is a DataAnalyzer a Calculations?
    How is a Calculations a ReadFile?
    ReadFile and Calculations sound like utility classes that can be used by the DataAnalyzer class.

    An example:
    given a class: Animal
    a Cat class can extend Animal because a cat is an animal

    If those classes need access to the contents of the other classes, create an instance and use that to access the contents of the class.
    If you don't understand my answer, don't ignore it, ask a question.

  5. #5
    Junior Member
    Join Date
    Mar 2021
    Location
    Ontario, Canada
    Posts
    27
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Default Re: Sorting a Multi-Dimensional String array

    Hello Norm,
    I've been playing with this this all day, first, I removed all the 'extends' as you made a very good point. Second, I tried to use the following code inside of a for loop,
    if(newArray[row][3] > newArray[row-1][3])

    but it tells me the following error: bad operand types for binary operator >

    We haven't touched on the "Comparator" function in java yet, I did watch a dozen youtube videos on this, but got even more confused.


    So to get me by, and so I can have a program that I can hand in, I am going to use the following to just sort the float[][] array that I created of just the data.
            Arrays.sort(arr, new Comparator<float[]>() {
     
                @Override
                public int compare(float[] val1, float[] val2) {
     
                    if (val1[columnSort] < val2[columnSort]) {
                        return 1;
                    } else {
                        return -1;
                    }
                }
            });

    and the following to print out the top 10,
            System.out.println("\n\tTop 10 based on their closing values.");
            System.out.printf("%-14s %-14s %-14s %-14s %-14s %-14s", "Open", "High", "Low", "Close", "Adj Close", "Volume");
            //printHeader();
            System.out.println();
            for (int row = 0; row < 10; row++) {                      
                for (int column = 0; column < dataArrayValues[0].length; column++) {
                    System.out.printf("%-15s", dataArrayValues[row][column]);
                }
                System.out.println();
     
        }

    it does display the top ten based on the 'Close' value, it just doesn't show the corresponding date, may lose a mark on this, but it is better than having that feature not working at all.

    I do have till Monday night to continue to play with it and possibly figure it out, if I do, I will re-post it here.

    Thanks for your time,

  6. #6
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    24,305
    Thanks
    54
    Thanked 2,635 Times in 2,585 Posts

    Default Re: Sorting a Multi-Dimensional String array

    bad operand types for binary operator >
    What are the data types for the operands? The > operator needs numeric like int or float.

    haven't touched on the "Comparator" function in java yet,
    Does that mean you can not use it?

    Separating the fields of a row into separate arrays does not work using the Arrays sort method with the array of just one field.
    If an array with the whole row were passed to the sort method, the compare method could pick out the fields from the row and compare them so that the sort method would sort the whole row with all the fields including the date.
    If you don't understand my answer, don't ignore it, ask a question.

  7. #7
    Junior Member
    Join Date
    Mar 2021
    Location
    Ontario, Canada
    Posts
    27
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Default Re: Sorting a Multi-Dimensional String array

    Hi Norm,
    I did it, it took a while to learn and understand the code but this is what I was able to come up with, (with a little help from Google)
        public void topTenDataArrayWithPrint() {
             Arrays.sort(newArray, new Comparator<String[]>() {
     
                @Override
                public int compare(final String[] first, final String[] second) {
                    return Double.valueOf(second[4]).compareTo(
                            Double.valueOf(first[4])
                    );
                }
            });
     
            System.out.println("\n\tTop 10 based on their closing values.");
            System.out.printf("%-14s %-14s %-14s %-14s %-14s %-14s %-14s", "Date", "Open", "High", "Low", "Close", "Adj Close", "Volume");
            System.out.println();
     
     
            for (int row = 0; row < 10; row++) {                      
                for (int column = 0; column < newArray[0].length; column++) {
                    System.out.printf("%-15s", newArray[row][column]);
                }
                System.out.println();
            }       
        }

    I believe this is what you were trying to explain to me before, all I know is that it works.

Similar Threads

  1. Multi dimensional array
    By suzy in forum What's Wrong With My Code?
    Replies: 6
    Last Post: August 21st, 2014, 07:08 AM
  2. How to define a multi-dimensional array?
    By javaiscool in forum What's Wrong With My Code?
    Replies: 2
    Last Post: October 28th, 2013, 11:40 PM
  3. Convert ArrayList to multi-dimensional array
    By dougie1809 in forum Loops & Control Statements
    Replies: 4
    Last Post: April 5th, 2013, 12:01 PM
  4. Replies: 3
    Last Post: October 26th, 2011, 03:37 PM
  5. Multi Dimensional Array help NEEDED URGENT
    By bonjovi4u in forum Loops & Control Statements
    Replies: 5
    Last Post: February 13th, 2010, 12:44 AM