La comparaison des tendances par paires entre les données est un scénario d'application très courant dans les applications d'analyse de données, comme indiqué ci-dessous :
Lot de tests simulés | Classe | Étudiants | Chinois | Mathématiques | Anglais |
---|---|---|---|---|---|
202302 | Classe tous les trois ans | Zhang Xiaoming | 130 | 145 | 133 |
202302 | Classe tous les trois ans | Wang Er Small | 1 28 | 138 | 140 |
202302 | Classe tous les trois ans | Xie Chunhua | 136 | 142 | 139 |
202301 | Classe tous les trois ans | Zhang Xiaoming | 132 | 140 | 128 |
202301 | Classe tous les trois ans | École primaire Wang Er | 125 | 146 | 142 |
202301 | Classe tous les trois ans | Xie Chunhua | 138 | 1 43 | 140 |
202212 | Classe tous les trois ans | Zhang Xiaoming | 135 | 138 | 120 |
202212 | Classe tous les trois ans | Wang Erxiao | 123 | 145 | 138 |
202212 | Classe Trois | Xie Chunhua | 136 | 140 | 142 |
Il est désormais nécessaire d'obtenir des données sur les progrès et le déclin des performances de chaque élève dans chaque matière dans différents lots d'examens. Comme suit
Lot de tests simulés | Classe | Étudiants | Chinois | Mathématiques | Anglais |
---|---|---|---|---|---|
Comparaison entre 202302 et 202301 | Classe de trois ans | Zhang Xiaoming | -2 | 5 | 5 |
Comparaison de 202302 et 202301 | Classe trois pendant trois ans | Wang Er Xiao | 3 | -8 | -2 |
Comparaison de 202302 et 202301 | Cours tous les trois ans | Xie Chunhua | -2 | -1 | -1 |
Comparaison 202301 et 202212 | Classe de trois ans | Zhang Xiaoming | -3 | 2 | 8 |
Comparaison entre 202301 et 202212 | Trois La première classe de l'année | Wang Er Xiao | 2 | 1 | 4 |
Comparaison entre 202301 et 202212 | La troisième classe de la troisième année | Xie Chunhua | 2 | 3 | -2 |
public class TrendCompare { /** * 主体的字段列表(如三年一班的张小明,那么主体字段列表为 班级 + 学生姓名) */ private String[] subjectFields; /** * 在某个字段的(介词) 如三年一班张晓明在不同考试批次的成绩对比结果 */ private String atField; /** * 参与趋势比较的字段集合 */ private String[] compareFields; /** * 赋值映射集合:给结果数据中指定的key设置指定的值 */ private Map<String, String> assignValMap; public String[] subjectFields() { return this.subjectFields; } public TrendCompare subjectFields(String... fields) { this.subjectFields = fields; return this; } public String atField() { return this.atField; } public TrendCompare atField(String field) { this.atField = field; return this; } public String[] compareFields() { return this.compareFields; } public TrendCompare compareFields(String... fields) { this.compareFields = fields; return this; } /** * 赋值操作 * * @param field * @param valueEL 值表达式 * @return */ public TrendCompare assignVal(String field, String valueEL) { if (assignValMap == null) { assignValMap = new HashMap<>(); } assignValMap.put(field, valueEL); return this; } public Map<String, String> assignValMap() { return this.assignValMap; } }
Cette classe définit les attributs suivants:
liste de champs du sujet
champ de préposition
liste des champs de comparaison
telles que : Chaque élève de chaque classedans différents lots d'examensLa progression et le déclin de chaque matière
Les exigences ci-dessus sont mappées au résultat de la définition de la classe comme suit :
La liste des champs de la matière (Classe, étudiants)
Champ de préposition (Lot d'examen)
Liste des champs pour comparaison (diverses matières : Chinois, Mathématiques, Anglais)
La classe fournit une méthode pour les appels externes comme suit
public static <T> List<T> compare(List<T> dataList, TrendCompare trendCompare) { Map<String, List<T>> groupMap = group(dataList, null, trendCompare.subjectFields()); List<T> resultList = new ArrayList<>(); for (List<T> groupDataList : groupMap.values()) { List<T> diffValueList = new ArrayList<>(); int size = groupDataList.size(); if (size > 1) { for (int i = 0; i < size - 1; i++) { //数据之间两两比较 diffValue = minuend - subtrahend T minuend = groupDataList.get(i); T subtrahend = groupDataList.get(i + 1); T diffValue = minus(trendCompare.compareFields(), minuend, subtrahend); //设置主体信息 if (trendCompare.subjectFields() != null) { for (String subjectField : trendCompare.subjectFields()) { setFieldValue(diffValue, subjectField, getFieldValue(minuend, subjectField)); } } //设置介词字段信息 String atField = trendCompare.atField(); if (StringUtils.isNotEmpty(atField)) { setFieldValue(diffValue, atField, getFieldValue(minuend, atField) + "与" + getFieldValue(subtrahend, atField) + "对比增减"); } diffValueList.add(diffValue); } } if (diffValueList.size() > 0) { T firstData = groupDataList.get(0); Map<String, Object> valMap = new HashMap<>(); //指定的赋值集合进行赋值 if (trendCompare.assignValMap() != null) { for (Map.Entry<String, String> stringStringEntry : trendCompare.assignValMap().entrySet()) { String field = stringStringEntry.getKey(); if (!StringUtils.equalsAny(field, trendCompare.compareFields())) { String valueEL = stringStringEntry.getValue(); valMap.put(field, executeSpEL(valueEL, firstData)); } } } for (Map.Entry<String, Object> entry : valMap.entrySet()) { for (T diffValue : diffValueList) { setFieldValue(diffValue, entry.getKey(), entry.getValue()); } } } resultList.addAll(diffValueList); } return resultList; }
Comme vous pouvez le voir, cette méthode nécessite l'entrée de
collecte de données
définition de comparaison de tendance
deux Paramètres, et renvoie enfin la comparaison de tendance L'ensemble de résultats final.
La logique interne de cette méthode peut être divisée en 2 étapes suivantes :
Grouper par sujet
Après le regroupement, comparez les données au sein du groupe par paires, et enfin renvoyez les résultats de la comparaison.
Supposons qu'il existe un ensemble de données comme suit
Définissez une classe d'élève :
public class Student { private String batch; private String banji; private String studentNo; private String name; private String sex; private Double yuwen; private Double math; private Double english; private Double physics; //extra private String maxScoreName1; public Student(String batch, String banji, String studentNo, String name, String sex, Double yuwen, Double math, Double english, Double physics) { this.batch = batch; this.banji = banji; this.studentNo = studentNo; this.name = name; this.sex = sex; this.yuwen = yuwen; this.math = math; this.english = english; this.physics = physics; } }
Nous écrivons une méthode qui renvoie les données ci-dessus :
public List<Student> getDataList() { List<Student> dataList = new ArrayList<>(); dataList.add(new Student("202302", "三年一班", "20001001", "张小明", "男", 130.0, 145.0, 133.0, 92.0)); dataList.add(new Student("202302", "三年一班", "20001002", "王二小", "男", 128.0, 138.0, 140.0, 98.0)); dataList.add(new Student("202302", "三年一班", "20001003", "谢春花", "女", 136.0, 142.0, 139.0, 95.0)); dataList.add(new Student("202302", "三年二班", "20002001", "冯世杰", "男", 129.0, 144.0, 138.0, 96.0)); dataList.add(new Student("202302", "三年二班", "20002002", "马功成", "男", 130.0, 132.0, 133.0, 98.0)); dataList.add(new Student("202302", "三年二班", "20002003", "魏翩翩", "女", 136.0, 142.0, 137.0, 92.0)); dataList.add(new Student("202301", "三年一班", "20001001", "张小明", "男", 132.0, 142.0, 134.0, 92.0)); dataList.add(new Student("202301", "三年一班", "20001002", "王二小", "男", 126.0, 136.0, 135.0, 94.0)); dataList.add(new Student("202301", "三年一班", "20001003", "谢春花", "女", 136.0, 145.0, 139.0, 95.0)); dataList.add(new Student("202301", "三年二班", "20002001", "冯世杰", "男", 124.0, 143.0, 148.0, 90.0)); dataList.add(new Student("202301", "三年二班", "20002002", "马功成", "男", 140.0, 133.0, 138.0, 90.0)); dataList.add(new Student("202301", "三年二班", "20002003", "魏翩翩", "女", 126.0, 136.0, 135.0, 92.0)); return dataList; }
Définition de comparaison de tendances et comparaison d'exécution :
List<Student> dataList = getDataList(); TrendCompare trendCompare = new TrendCompare() .subjectFields("banji", "name") .atField("batch") .compareFields("yuwen", "math", "english") //.assignVal("batch", "'环比增减'") ; List<Student> resultList = DataProcessUtil.compare(dataList, trendCompare); for (Student result : resultList) { System.out.println(JSON.toJSONString(result)); }
Les résultats sont les suivants :
{"banji":"三年一班","batch":"202302与202301对比增减","english":-1.0,"math":3.0,"name":"张小明","yuwen":-2.0} {"banji":"三年一班","batch":"202302与202301对比增减","english":5.0,"math":2.0,"name":"王二小","yuwen":2.0} {"banji":"三年一班","batch":"202302与202301对比增减","english":0.0,"math":-3.0,"name":"谢春花","yuwen":0.0} {"banji":"三年二班","batch":"202302与202301对比增减","english":-10.0,"math":1.0,"name":"冯世杰","yuwen":5.0} {"banji":"三年二班","batch":"202302与202301对比增减","english":-5.0,"math":-1.0,"name":"马功成","yuwen":-10.0} {"banji":"三年二班","batch":"202302与202301对比增减","english":2.0,"math":6.0,"name":"魏翩翩","yuwen":10.0}
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!