Вычисление данных на основании двух массивов
Стоит задача реализовать метод:
public String getSalaryInfo(String[] names, String[] data, String dateFrom, String dateTo)
где
String[] names- массив фамилий сотрудников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уе в этот день он заработал)
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;
}
Заранее благодарю всех за помощь.
Ответы (1 шт):
Следует создать классы для представления строки данных (похожий вопрос: База данных на 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
Михайлов - ---