数据处理

起床搬砖 2021-04-02 11:10:55


如上图左边所示,在一个Excel文件中,第一行可以不读,第二行中表头的‘级别’数量不定,有可能为3/4/5/...列对应3/4/5/...级,后面编号/名称/规格/单位/数量5列固定。

需求:类似于制造业的BOM,将数据按照层级拆分开来如图中右边所示。
难点①解析文件中‘级别’数量 已通过(获取最大列数-5)解决;
难点②按照从上往下读取的顺序,级别1下面只跟自己下面的级别2,比级别2大的跳过,若后面再次出现级别1,那么第二次出现级别1后面的级别2归为第二次的级别1(一般一个文件中只有一个级别1);
级别2下面只跟自己下面的级别3,比级别3大的跳过,若后面再次出现级别2,那么第二次出现级别2后面的级别3归为第二次的级别2;
级别3下面只跟自己下面的级别4,比级别4大的跳过,若后面再次出现级别3,那么第二次出现级别3后面的级别4归为第二次的级别3;
如此类推。
难点③最后希望以List<List<String>> List = new ArrayList<List<String>>(); 类型存储,将拆分出来的每一组独立出来。

自己写了两天这逻辑...感觉怎么写都解决不了级别3只能跟在上一次出现的2上,遇到下个2跳出,然后继续拆分下一条
各位大神帮忙看看能不能解决,谢谢谢谢!
...全文
551 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
起床搬砖 2021-04-07
  • 打赏
  • 举报
回复
已经解决了 谢谢两位。
冰思雨 2021-04-06
  • 打赏
  • 举报
回复
上代码:
import java.util.ArrayList;
import java.util.List;

public class Record {
    /**
     * 级别
     */
    private int level;
    /**
     * 编号
     */
    private int number;
    /**
     * 名称
     */
    private String name;
    /**
     * 规格
     */
    private String standard;
    /**
     * 单位
     */
    private String unit;
    /**
     * 数量
     */
    private int quantity;

    public Record() { }

    public Record(int level, int number, String name, String standard, String unit, int quantity) {
        this.level = level;
        this.number = number;
        this.name = name;
        this.standard = standard;
        this.unit = unit;
        this.quantity = quantity;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getStandard() {
        return standard;
    }

    public void setStandard(String standard) {
        this.standard = standard;
    }

    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    public static void main(String[] args) {
        // 1. 初始化数据
        List<Record> records = new ArrayList<>();
        records.add(new Record(1,1,"1","1","套", 0));
        records.add(new Record(2,2,"2","2","套", 1));
        records.add(new Record(3,3,"3","3","套", 1));
        records.add(new Record(3,4,"4","4","个", 2));
        records.add(new Record(2,5,"5","5","个", 1));
        records.add(new Record(2,6,"6","6","套", 1));
        records.add(new Record(3,7,"7","7","个", 1));
        records.add(new Record(3,8,"8","8","个", 4));
        records.add(new Record(3,9,"9","9","套", 1));
        records.add(new Record(4,10,"10","10","套", 1));
        records.add(new Record(4,11,"11","11","克", 0));
        records.add(new Record(3,12,"12","12","套", 1));
        records.add(new Record(4,13,"13","13","克", 0));
        records.add(new Record(2,14,"14","14","个", 1));
        records.add(new Record(3,15,"15","15","套", 1));
        records.add(new Record(4,16,"16","16","克", 0));
        records.add(new Record(3,17,"17","17","套", 1));
        records.add(new Record(4,18,"18","18","克", 0));
        records.add(new Record(5,19,"19","19","克", 0));
        records.add(new Record(5,20,"20","20","克", 0));
        records.add(new Record(4,21,"21","21","克", 0));
        records.add(new Record(3,22,"22","22","套", 1));
        records.add(new Record(2,23,"23","23","个", 1));
        //2. 获取最大级别和最小级别
        int minLevel = 1, maxLevel = 1;
        for (Record record : records) {
            minLevel = minLevel > record.getLevel() ? record.getLevel() : minLevel;
            maxLevel = maxLevel < record.getLevel() ? record.getLevel() : maxLevel;
        }
        //3. 按照级别分组
        List<List<Record>> groups = new ArrayList<>();
        for (int level = minLevel; level < maxLevel; level++) {
            List<Record> group = null;
            for (Record record : records) {
                if (group == null) {
                    group = new ArrayList<>();
                }
                if (record.getLevel() == level) {
                    if (group.isEmpty()) {
                        group.add(record);
                    } else if (group.get(group.size()-1).getLevel() == level) {
                        group.clear();
                        group.add(record);
                    } else {
                        groups.add(group);
                        group = new ArrayList<>();
                        group.add(record);
                    }
                    continue;
                }
                if (record.getLevel() == level+1) {
                    group.add(record);
                }
            }
            if (group != null && group.size()>1) {
                groups.add(group);

            }
            group = null;
        }
        //4. 打印输出
        for (List<Record> group : groups) {
            for (Record record : group) {
                System.out.println(String.format("%2d %2d %2s %2s %s %2d",
                        record.getLevel(), record.getNumber(), record.getName(),
                        record.getStandard(), record.getUnit(), record.getQuantity()));
            }
            System.out.println();
        }
    }
}
输出结果:
 1  1  1  1 套  0
 2  2  2  2 套  1
 2  5  5  5 个  1
 2  6  6  6 套  1
 2 14 14 14 个  1
 2 23 23 23 个  1

 2  2  2  2 套  1
 3  3  3  3 套  1
 3  4  4  4 个  2

 2  6  6  6 套  1
 3  7  7  7 个  1
 3  8  8  8 个  4
 3  9  9  9 套  1
 3 12 12 12 套  1

 2 14 14 14 个  1
 3 15 15 15 套  1
 3 17 17 17 套  1
 3 22 22 22 套  1

 3  9  9  9 套  1
 4 10 10 10 套  1
 4 11 11 11 克  0

 3 12 12 12 套  1
 4 13 13 13 克  0

 3 15 15 15 套  1
 4 16 16 16 克  0

 3 17 17 17 套  1
 4 18 18 18 克  0
 4 21 21 21 克  0

 4 18 18 18 克  0
 5 19 19 19 克  0
 5 20 20 20 克  0

起床搬砖 2021-04-02
  • 打赏
  • 举报
回复
引用 5 楼 长江水面写日记 的回复:
// 首先要把数据处理成这个map key=>级别 value=>表里的行索引
	private static Map<Integer, List<Integer>> ALL_DATA = null;
	//  你的数据
	private static List<List<String>> Lists = new ArrayList<List<String>>();

	private static void recursion(Integer level, Integer rowIndex) {
		Integer nextLevel = level + 1;
		if (CollectionUtils.isNotEmpty(ALL_DATA.get(nextLevel))) {
			List<Integer> levleList = ALL_DATA.get(level);
			if (levleList.size() - 1 == levleList.indexOf(rowIndex)) {
				// todo 拿到他级别下的下一级别,输出
			} else {
				Integer nextRowIndex = levleList.get(levleList.indexOf(rowIndex) + 1);
				List<Integer> newLevleList = ALL_DATA.get(nextLevel);
				// 筛选出该级别下的下一级别的表的行索引
				List<Integer> collect = newLevleList.stream().filter(a -> a > rowIndex && a < nextRowIndex).collect(Collectors.toList());
				// todo 输出
			}
			for (int i = 0; i < ALL_DATA.get(nextLevel).size(); i++) {
				recursion(nextLevel, i);
			}
		}
	}
我先琢磨一下 感谢!
  • 打赏
  • 举报
回复
// 首先要把数据处理成这个map key=>级别 value=>表里的行索引
	private static Map<Integer, List<Integer>> ALL_DATA = null;
	//  你的数据
	private static List<List<String>> Lists = new ArrayList<List<String>>();

	private static void recursion(Integer level, Integer rowIndex) {
		Integer nextLevel = level + 1;
		if (CollectionUtils.isNotEmpty(ALL_DATA.get(nextLevel))) {
			List<Integer> levleList = ALL_DATA.get(level);
			if (levleList.size() - 1 == levleList.indexOf(rowIndex)) {
				// todo 拿到他级别下的下一级别,输出
			} else {
				Integer nextRowIndex = levleList.get(levleList.indexOf(rowIndex) + 1);
				List<Integer> newLevleList = ALL_DATA.get(nextLevel);
				// 筛选出该级别下的下一级别的表的行索引
				List<Integer> collect = newLevleList.stream().filter(a -> a > rowIndex && a < nextRowIndex).collect(Collectors.toList());
				// todo 输出
			}
			for (int i = 0; i < ALL_DATA.get(nextLevel).size(); i++) {
				recursion(nextLevel, i);
			}
		}
	}
  • 打赏
  • 举报
回复
你要先处理成Map<Integer,List<integer>> 这个才行,你这个List<List<String>>只是把每行的数据拿出来了,每个级别在哪一行不清楚啊
起床搬砖 2021-04-02
  • 打赏
  • 举报
回复
引用 2 楼 长江水面写日记 的回复:
你这个不能边读取边输出, 应该先完整把数据读入内存. 在内存里,可以用Map<Integer,List<integer>> 的方式记录数据 ,key是 级别 ,List<integer>是该级别所在行的索引值的集合(从上到下的顺序), 读取完后,你的map就存好了全局信息.就可以递归了 , 调用递归方法传入两个参数 :级别=1,级别1的索引=0 , 然后 key+1=2, 拿2去判断下面有没有list,如果有, 遍历级别2, 然后 调用递归方法 传入级别2, 改级别2的索引, 一直递归直到判定条件是级别5, 这时候在级别5,传参里你知道了级别4的索引是多少,拿级别4的索引,找到他下一个索引. 你就拿到了级别5的表的行索引的范围. 就能拆出来最低级的表了.
在读取Excel时我是直接将所有数据一次性拿出来的,用List<List<String>> List = new ArrayList<List<String>>();这个类型,List.get(0)就是Excel的第一条数据,get(1)就是第二条,类推。 关键是后面这批数据怎么拆出一组一组的List<List<String>>这个逻辑,一直写不通。。方便的话可以代码示范一下吗?
  • 打赏
  • 举报
回复
你这个不能边读取边输出, 应该先完整把数据读入内存. 在内存里,可以用Map<Integer,List<integer>> 的方式记录数据 ,key是 级别 ,List<integer>是该级别所在行的索引值的集合(从上到下的顺序), 读取完后,你的map就存好了全局信息.就可以递归了 , 调用递归方法传入两个参数 :级别=1,级别1的索引=0 , 然后 key+1=2, 拿2去判断下面有没有list,如果有, 遍历级别2, 然后 调用递归方法 传入级别2, 改级别2的索引, 一直递归直到判定条件是级别5, 这时候在级别5,传参里你知道了级别4的索引是多少,拿级别4的索引,找到他下一个索引. 你就拿到了级别5的表的行索引的范围. 就能拆出来最低级的表了.
起床搬砖 2021-04-02
  • 打赏
  • 举报
回复

62,634

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧