Search code examples
salesforceapexsalesforce-lightning

Salesforce Apex class to sort years and year ranges giving incorrect output


Tried writing a sort method where input was given like a string of comma-delimited years and year ranges String input = '2017, 2018,2020-2023,1800-1700,2020,20a9,19z5-1990,2025,20261,2013';

Expectation is to get a string of comma-delimited years and year ranges,and remove all duplicates and invalid inputs.

Below is class written which is not giving me correct output

            public class sortYearAndYearRangesString {
              public static List<String> sortSpecialString(String input) {
                   system.debug(input);
                    List<String> inputList = input.split('');
                  system.debug(inputList);
                Map<Integer,String> stringMap = new Map<Integer,String>();
                  system.debug(stringMap);
                List<String> output = new List<String>();
                for (Integer i=0; i<inputList.size(); i++) {
                    String charac = inputList[i];
                    if(!charac.isAlphaNumeric()) {
                         system.debug(charac);
                        stringMap.put(i,charac);
                    }else {
                        output.add(charac);
                        system.debug(output);
                    }
                }
                String finalString =  String.join(output,'');
                  system.debug(finalString);
                List<String> resultList = finalString.reverse().split('');
                for( Integer I : stringMap.keySet() ){
                    system.debug(I);
                    resultList.add(I,stringMap.get(I));
                     system.debug(resultList);
                    
                   
                }
                  return resultList;      
                   }
                   
                   

Tried validating the solution in Anonymous Apex but no success

             public static void validateSolution() {
             String input = '2017, 2018,2020-2023,1800-1700,2020,20a9,19z5-1990,2025,20261,2013';
             List<Integer> expected = new List<Integer> {2013,2017,2018,2020,2021,2022,2023,2025};
             List<Integer> actual = sortYearAndYearRangesString(input);
             
             System.assertEquals(expected, actual, 'Invalid Results');
             }
            }

Your help is appreciated

Regards

Carolyn


Solution

  • According to your test case, you should also define at least a constant for a maximum value, in order to exclude 20261. Probably you need a minimum too.
    I used 1700 as min and 4000 as max because these are the limits for a Date or Datatime field: docs
    Moreover the method must return a List<Integer> instead of a List<String>.
    You don't need a Map, just a Set would work.

    public class SortYearAndYearRangesString {
        private static final Integer MAX_YEAR = 4000;
        private static final Integer MIN_YEAR = 1700;
    
        public static List<Integer> sortSpecialString(String input) {
            Set<Integer> output = new Set<Integer>();
            List<String> yearsList = input.split(',');
            for (String yearString : yearsList) {
                yearString = yearString.trim();
                if (yearString.isNumeric()) {
                    try {
                        Integer year = Integer.valueOf(yearString);
                        if (year >= MIN_YEAR && year <= MAX_YEAR) {
                            output.add(year);
                        }
                    } catch (TypeException e) {
                        System.debug(e.getMessage());
                    }
                } else {
                    List<String> range = yearString.split('-');
                    if (range.size() == 2 && range[0].isNumeric() && range[1].isNumeric()) {
                        try {
                            // Modify the following two lines once you know how to handle range like 1300-1500 or 3950-4150
                            Integer firstYear = Math.max(Integer.valueOf(range[0]), MIN_YEAR);
                            Integer lastYear = Math.min(Integer.valueOf(range[1]), MAX_YEAR);
                            while (firstYear <= lastYear) {
                                output.add(firstYear++);
                            }
                        } catch (TypeException e) {
                            System.debug(e.getMessage());
                        }
                    }
                }
            }
            List<Integer> sortedYears = new List<Integer>(output);
            sortedYears.sort();
            return sortedYears;
        }
    }
    

    If a range that exceed the boundaries (like 1300-1500 or 3950-4150) should be treated as invalid and skipped, please change these lines

    Integer firstYear = Math.max(Integer.valueOf(range[0]), MIN_YEAR);
    Integer lastYear = Math.min(Integer.valueOf(range[1]), MAX_YEAR);
    while (firstYear <= lastYear) {
        output.add(firstYear++);
    }
    

    as follow:

    Integer firstYear = Integer.valueOf(range[0]);
    Integer lastYear = Integer.valueOf(range[1]);
    if (firstYear >= MIN_YEAR && lastYear <= MAX_YEAR) {
        while (firstYear <= lastYear) {
            output.add(firstYear++);
        }
    }
    

    I tested it in anonymous console with the following code:

    String input = '2017, 2018,2020-2023,1800-1700,2020,20a9,19z5-1990,2025,20261,2013';
    List<Integer> expected = new List<Integer> {2013,2017,2018,2020,2021,2022,2023,2025};
    List<Integer> actual = SortYearAndYearRangesString.sortSpecialString(input);
    System.debug(actual);
    System.assertEquals(expected, actual, 'Invalid Results');
    
    input = '1500,2017, 2018,2020-2023,1800-1700,2020,20a9,19z5-1990,2025,20261,2013,3998-4002';
    expected = new List<Integer> {2013,2017,2018,2020,2021,2022,2023,2025,3998,3999,4000};
    actual = SortYearAndYearRangesString.sortSpecialString(input);
    System.assertEquals(expected, actual, 'Invalid Results');