英文:
How do I convert weekly data to a monthly data from a nested map structure
问题
import java.util.*;
import java.util.stream.Collectors;
public class WeeklyToMonthlyConverter {
public static Map<String, Map<String, Object>> convertToMonthlyData(Map<String, Map<String, Object>> weeklyData) {
return weeklyData.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().entrySet().stream()
.collect(Collectors.groupingBy(
weekEntry -> weekEntry.getKey().substring(0, 7),
Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
WeeklyToMonthlyConverter::sumData
)
))
));
}
private static Map<String, Object> sumData(Map<String, Object> targetMap, Map<String, Object> sourceMap) {
for (Map.Entry<String, Object> entry : sourceMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof Number) {
if (targetMap.containsKey(key)) {
Number existingValue = (Number) targetMap.get(key);
double sum = existingValue.doubleValue() + ((Number) value).doubleValue();
targetMap.put(key, sum);
} else {
targetMap.put(key, value);
}
}
}
return targetMap;
}
public static void main(String[] args) {
// ... (rest of your code remains the same)
}
private static Map<String, Object> createWeeklyObject(int productSales, int noOfUnitsSold, int customerViews, double conversion) {
// ... (rest of your code remains the same)
}
}
这里是使用 lambda 和 streams 重写了你的 convertToMonthlyData
方法。这个版本更为简洁,但实现的功能与之前的版本相同。
英文:
I have a some data in Java which is in the format Map<String, Map<String, Object>>
Let's say we have 2 countries and also assume that we have weekly data for each country, which means the last 60 days will have a data of something like this:
{
"US”= {
"2023-01-02”={
"customerViews"= 2500,
"productSales"= 1200,
"noOfUnitsSold"= 600,
"conversion"= 0.24
},
"2023-01-09”={
"customerViews"= 2900,
"productSales"= 1400,
"noOfUnitsSold"= 700,
"conversion"= 0.24
},
"2023-01-16”= {
"customerViews"= 2000,
"productSales"= 1000,
"noOfUnitsSold"= 500,
"conversion"= 0.25
},
"2023-02-23”= {
"customerViews"= 2700,
"productSales"= 1300,
"noOfUnitsSold"= 650,
"conversion"= 0.22
},
"2023-01-30”={
"customerViews"= 1800,
"productSales"= 900,
"noOfUnitsSold"= 450,
"conversion"= 0.21
},
"2023-02-06”= {
"customerViews"= 2300,
"productSales"= 1100,
"noOfUnitsSold"= 550,
"conversion"= 0.23
},
"2023-02-13”= {
"customerViews"= 2000,
"productSales"= 1000,
"noOfUnitsSold"= 500,
"conversion"= 0.25
},
"2023-02-20”= {
"customerViews"= 2500,
"productSales"= 1200,
"noOfUnitsSold"= 600,
"conversion"= 0.24
}
},
"CA”= {
"2023-01-02”= {
"customerViews"= 2000,
"productSales"= 1000,
"noOfUnitsSold"= 500,
"conversion"= 0.24
},
"2023-01-23”= {
"customerViews"= 2200,
"productSales"= 1100,
"noOfUnitsSold"= 550,
"conversion"= 0.22
},
"2023-01-30”={
"customerViews"= 1800,
"productSales"= 900,
"noOfUnitsSold"= 450,
"conversion"= 0.22
},
"2023-02-06”= {
"customerViews"= 1700,
"productSales"= 850,
"noOfUnitsSold"= 425,
"conversion"= 0.21
},
"2023-02-13”= {
"customerViews"= 2000,
"productSales"= 1000,
"noOfUnitsSold"= 500,
"conversion"= 0.24
}
}
}
The reason I didn't include few weeks of data for 2nd country is because, there might be a case where there are no data for that week. So in that case there will be no entries for that week.
Now, I want to take this data as a input and convert to a monthly data which in turn the response looks like this:
{
"US"= {
"2023-01"= {
"customerViews"= 12400.0,
"productSales"= 6000.0,
"noOfUnitsSold"= 3000.0,
"conversion"= 1.18
},
"2023-02"= {
"customerViews"= 6300.0,
"productSales"= 3100.0,
"noOfUnitsSold"= 1550.0,
"conversion"= 0.7
}
},
"CA"= {
"2023-01"= {
"customerViews"= 4150.0,
"productSales"= 2050.0,
"noOfUnitsSold"= 1025.0,
"conversion"= 0.45
},
"2023-02"= {
"customerViews"= 3500.0,
"productSales"= 1750.0,
"noOfUnitsSold"= 875.0,
"conversion"= 0.43
}
}
}
This is what I tried:
import java.util.*;
public class WeeklyToMonthlyConverter {
public static Map<String, Map<String, Object>> convertToMonthlyData(Map<String, Map<String, Object>> weeklyData) {
Map<String, Map<String, Object>> monthlyData = new HashMap<>();
for (Map.Entry<String, Map<String, Object>> countryEntry : weeklyData.entrySet()) {
String countryId = countryEntry.getKey();
Map<String, Object> weeklyMap = countryEntry.getValue();
Map<String, Object> monthlyMap = new HashMap<>();
for (Map.Entry<String, Object> weekEntry : weeklyMap.entrySet()) {
String weekDate = weekEntry.getKey();
Object weekData = weekEntry.getValue();
String month = weekDate.substring(0, 7); // Extract the year and month
if (monthlyMap.containsKey(month)) {
// If the month entry exists, sum the values
Map<String, Object> existingMonthData = (Map<String, Object>) monthlyMap.get(month);
sumData(existingMonthData, (Map<String, Object>) weekData);
} else {
// If the month entry does not exist, initialize it with the weekly data
monthlyMap.put(month, weekData);
}
}
monthlyData.put(countryId, monthlyMap);
}
return monthlyData;
}
private static void sumData(Map<String, Object> targetMap, Map<String, Object> sourceMap) {
for (Map.Entry<String, Object> entry : sourceMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof Number) {
// If the value is numeric, sum it with the existing value
if (targetMap.containsKey(key)) {
Number existingValue = (Number) targetMap.get(key);
double sum = existingValue.doubleValue() + ((Number) value).doubleValue();
targetMap.put(key, sum);
} else {
targetMap.put(key, value);
}
}
}
}
public static void main(String[] args) {
Map<String, Map<String, Object>> weeklyData = new HashMap<>();
Map<String, Object> usWeeklyData = new HashMap<>();
usWeeklyData.put("2023-01-02", createWeeklyObject(1000, 500, 2000, 0.25));
usWeeklyData.put("2023-01-09", createWeeklyObject(1200, 600, 2500, 0.24));
usWeeklyData.put("2023-01-16", createWeeklyObject(1100, 550, 2300, 0.23));
usWeeklyData.put("2023-01-23", createWeeklyObject(1300, 650, 2700, 0.22));
usWeeklyData.put("2023-01-30", createWeeklyObject(1400, 700, 2900, 0.24));
usWeeklyData.put("2023-02-06", createWeeklyObject(900, 450, 1800, 0.21));
usWeeklyData.put("2023-02-13", createWeeklyObject(1000, 500, 2000, 0.25));
usWeeklyData.put("2023-02-20", createWeeklyObject(1200, 600, 2500, 0.24));
weeklyData.put("US", usWeeklyData);
Map<String, Object> caWeeklyData = new HashMap<>();
caWeeklyData.put("2023-01-02", createWeeklyObject(800, 400, 1800, 0.22));
caWeeklyData.put("2023-01-23", createWeeklyObject(950, 475, 1950, 0.23));
caWeeklyData.put("2023-01-30", createWeeklyObject(1100, 550, 2200, 0.22));
caWeeklyData.put("2023-02-06", createWeeklyObject(850, 425, 1700, 0.21));
caWeeklyData.put("2023-02-13", createWeeklyObject(900, 450, 1800, 0.22));
weeklyData.put("CA", caWeeklyData);
System.out.println(weeklyData);
// Convert to monthly data
Map<String, Map<String, Object>> monthlyData = convertToMonthlyData(weeklyData);
System.out.println(monthlyData);
}
private static Map<String, Object> createWeeklyObject(int productSales, int noOfUnitsSold, int customerViews, double conversion) {
Map<String, Object> weeklyObject = new HashMap<>();
weeklyObject.put("productSales", productSales);
weeklyObject.put("noOfUnitsSold", noOfUnitsSold);
weeklyObject.put("customerViews", customerViews);
weeklyObject.put("conversion", conversion);
return weeklyObject;
}
}
I don't have much hand's on experience using lambda and streams for which I think using these concepts, this can be made even more efficiently. Can you please guide me on this one?
Thanks in advance
答案1
得分: 3
使用Java Streams,您可以参考下面的代码:
private static Map<String, Map<String, Map<String, Object>>> convertToMonthlyData(Map<String, Map<String, Object>> weeklyData) {
DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
Map<String, Map<String, Map<String, Object>>> monthwiseMap = new HashMap<>();
weeklyData.forEach((country, weeklyDataDetail) -> {
Map<String, Map<String, Object>> countryMonthwiseMap = weeklyDataDetail.entrySet().stream()
.collect(Collectors.groupingBy(entry -> YearMonth.parse(entry.getKey(), weekFormatter).format(monthFormatter),
Collectors.mapping(Map.Entry::getValue, Collectors.toList())))
.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> combineWeeklyData(entry.getValue())));
monthwiseMap.put(country, countryMonthwiseMap);
});
return monthwiseMap;
}
private static Map<String, Object> combineWeeklyData(List<Object> weeklyData) {
Map<String, Object> combinedData = new HashMap<>();
int totalCustomerViews = 0;
int totalProductSales = 0;
int totalNoOfUnitsSold = 0;
double totalConversion = 0.0;
for (Object data : weeklyData) {
if (data instanceof Map) {
Map<String, Object> weeklyDataMap = (Map<String, Object>) data;
totalCustomerViews += (int) weeklyDataMap.get("customerViews");
totalProductSales += (int) weeklyDataMap.get("productSales");
totalNoOfUnitsSold += (int) weeklyDataMap.get("noOfUnitsSold");
totalConversion += (double) weeklyDataMap.get("conversion");
}
}
int numWeeks = weeklyData.size();
double averageConversion = (numWeeks > 0) ? totalConversion / numWeeks : 0.0;
combinedData.put("customerViews", totalCustomerViews);
combinedData.put("productSales", totalProductSales);
combinedData.put("noOfUnitsSold", totalNoOfUnitsSold);
combinedData.put("conversion", averageConversion);
return combinedData;
}
这是您提供的Java代码的翻译部分。如果您有任何其他疑问,请随时提出。
英文:
Using Java Streams you can refer below code
private static Map<String, Map<String, Map<String, Object>>> convertToMonthlyData(Map<String, Map<String, Object>> weeklyData) {
DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
Map<String, Map<String, Map<String, Object>>> monthwiseMap = new HashMap<>();
weeklyData.forEach((country, weeklyDataDetail) -> {
Map<String, Map<String, Object>> countryMonthwiseMap = weeklyDataDetail.entrySet().stream()
.collect(Collectors.groupingBy(entry -> YearMonth.parse(entry.getKey(), weekFormatter).format(monthFormatter),
Collectors.mapping(Map.Entry::getValue, Collectors.toList())))
.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> combineWeeklyData(entry.getValue())));
monthwiseMap.put(country, countryMonthwiseMap);
});
return monthwiseMap;
}
private static Map<String, Object> combineWeeklyData(List<Object> weeklyData) {
Map<String, Object> combinedData = new HashMap<>();
int totalCustomerViews = 0;
int totalProductSales = 0;
int totalNoOfUnitsSold = 0;
double totalConversion = 0.0;
for (Object data : weeklyData) {
if (data instanceof Map) {
Map<String, Object> weeklyDataMap = (Map<String, Object>) data;
totalCustomerViews += (int) weeklyDataMap.get("customerViews");
totalProductSales += (int) weeklyDataMap.get("productSales");
totalNoOfUnitsSold += (int) weeklyDataMap.get("noOfUnitsSold");
totalConversion += (double) weeklyDataMap.get("conversion");
}
}
int numWeeks = weeklyData.size();
double averageConversion = (numWeeks > 0) ? totalConversion / numWeeks : 0.0;
combinedData.put("customerViews", totalCustomerViews);
combinedData.put("productSales", totalProductSales);
combinedData.put("noOfUnitsSold", totalNoOfUnitsSold);
combinedData.put("conversion", averageConversion);
return combinedData;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论