Вычисление данных на основании двух массивов

Рейтинг: -3Ответов: 1Опубликовано: 14.03.2023

Стоит задача реализовать метод:

public String getSalaryInfo(String[] names, String[] data, String dateFrom, String dateTo)

где

  1. String[] names - массив фамилий сотрудников
  2. String[] data - массив данных для вычисления заработной платы в формате:
    "26.04.2019 Иванов 4 50" 
    "26.04.2019 Петров 4 50"
    //   05.04.2019 Сидоров 3 200
    //   10.04.2019 Семенова 7 100
    //   22.04.2019 Семенова 9 100
    //   25.06.2019 Иванов 11 50
    //   26.04.2019 Петров 3 150
    //   13.02.2019 Сидоров 7 100
    //   26.04.2019 Сидоров 9 100

где числа 4 и 50 данные для вычисления зп (4часа*50уе-200уе в этот день он заработал)

  1. dateFrom, dateTo соответственно данные за какой период посчитать зп сотрудников.

Нужно реализовать методы, чтобы отображалась информация в формате:

Отчет за период #дата_1# - #дата_2#
#Имя сотрудника# - #заработанные деньги#
****Report for period 01.04.2019  - 30.04.2019**  
Иванов - 200
Петров - 650
Сидоров - 1500**

Пока солянка получилась такая, но код не работает корректно (((

    public String getSalaryInfo(String[] names, String[] data, String dateFrom, String dateTo) {
            String month = dateFrom.substring(3, 5);
            String nameOfEmployee = "";
            int sumSalary = 0;
            for (int i = 0; i < data.length; i++) {
                for (int j = 0; j < names.length; j++) {
                    if (data[i].contains(names[j]) && month.equals(data[i].substring(3, 5))) {
                        nameOfEmployee = names[j];
                        String dataValue = data[i].substring(data[i].indexOf(" "));
                        int l = dataValue.length();
                        int sum = 0;
                        String temp = "";
                        for (int k = 0; k < l; k++)
                        {
                            if (Character.isDigit(dataValue.charAt(k)))
                            {
                                if (k < l-1 && Character.isDigit(dataValue.charAt(k+1)))
                                {
                                    temp += dataValue.charAt(k);
                                }
                                else
                                {
                                    temp += dataValue.charAt(k);
                                    sum += Integer.parseInt(temp);
                                    temp = "";
                                }
                            }
                        }
                    }
                }
    
    
            }
            String resultAnswer = "Report for period " + dateFrom + "-" + dateTo + nameOfEmployee + " "
                    + sumSalary;
    
            return resultAnswer;
        }

Заранее благодарю всех за помощь.

Ответы

▲ 0Принят

Следует создать классы для представления строки данных (похожий вопрос: База данных на java) и для агрегации данных для отчёта (вычисления суммарной зарплаты по произведению часов на ставку). Также необходимо корректно реализовать парсинг даты в формате dd.mm.yyyy и метод для фильтрации даты в списке.

С использованием кортежей record в Java 16+ реализация класса достаточно тривиальна, однако потребуется написать конструктор/метод для парсинга строки:

record DataRow(LocalDate date, String name, int hours, int rate) {}

public static final DateTimeFormatter DDMMYYYY = DateTimeFormatter.ofPattern("dd.MM.yyyy");

public static DataRow parse(String str) {
    String[] cols = str.split("\\s+"); // разбить на колонки
    return new DataRow(
        LocalDate.parse(cols[0], DDMMYYYY), // дата
        cols[1],                            // имя
        Integer.parseInt(cols[2]),          // часы
        Integer.parseInt(cols[3])           // почасовой тариф
    );
}

Метод для фильтра по дате может быть такой:

public static boolean between(LocalDate d, LocalDate from, LocalDate to) {
    return d.isAfter(from) || d.isEqual(from) && d.isBefore(to);
}

Тогда реализация метода может выглядеть так (используя Stream API для краткости):

public String getSalaryInfo(String[] names, String[] data, String dateFrom, String dateTo) {
    LocalDate from = LocalDate.parse(dateFrom, DDMMYYYY);
    LocalDate to = LocalDate.parse(dateTo, DDMMYYYY);

    Set<String> set = Set.of(names);

    Map<String, Integer> salaryMap = Arrays.stream(data)
        .map(row -> parse(row)) // Stream<DataRow>
        .filter(row -> set.contains(row.name()) && between(row.date(), from, to))
        .collect(Collectors.groupingBy(
            DataRow::name,
            Collectors.summingInt(row -> row.hours() * row.rate())
        ));

    StringBuilder sb = new StringBuilder();
    sb.append("**** Report for period ")
      .append(dateFrom).append(" - ").append(dateTo).append(" ****\n");
    Arrays.stream(names)
        .forEach(name -> sb
            .append(name)
            .append(" - ")
            .append(salaryMap.containsKey(name) 
                ? String.valueOf(salaryMap.get(name)) 
                : "---"
            )
            .append("\n")
        );
    return sb.toString();  
}

Тест:

String[] data = {
    "26.04.2019 Иванов 4 50", 
    "26.04.2019 Петров 4 50",
    "05.04.2019 Сидоров 3 200",
    "10.04.2019 Семенова 7 100",
    "22.04.2019 Семенова 9 100",
    "25.06.2019 Иванов 11 50",
    "26.04.2019 Петров 3 150",
    "13.02.2019 Сидоров 7 100",
    "26.04.2019 Сидоров 9 100"
};

String[] names = {"Иванов", "Петров", "Сидоров", "Михайлов"};

System.out.println(getSalaryInfo(names, data, "01.04.2019", "01.05.2019"));

Результат:

**** Report for period 01.04.2019 - 01.05.2019 ****
Иванов - 750
Петров - 650
Сидоров - 1500
Михайлов - ---