将集合中的垂直值迭代为另一个集合中的水平值

时间:2013-12-20 09:53:08

标签: java string list

我的java程序中有一些字符串列表,如下所示:

List<String> input = new ArrayList<String>();

    input.add("2013-07-31,A,47");
    input.add("2013-06-28,A,52");
    input.add("2013-05-31,A,63");

    input.add("2013-07-31,B,47");
    input.add("2013-06-28,B,54");
    input.add("2013-05-31,B,91");

    input.add("2013-07-31,C,78");
    input.add("2013-06-28,C,24");

    input.add("2013-07-31,D,99");
    input.add("2013-05-31,D,82");

在每个字符串中,逗号分隔的第一个标记表示日期,第二个标记是产品名称,第三个标记是价格。

我想使用上面的列表生成下表格式的Excel报告:

Prod   |           Price
---------------------------------------------
  XXX    |   M1        M2        M3
---------------------------------------------
  A      |   47        52        63
  B      |   47        54        91
  C      |   78        24        00
  D      |   99        00        82
---------------------------------------------

M1为2013-07-31,M2为2013-06-28,而M3为2013-05-31。

为了实现这一点,我的输出集合应该是一个带有成员字符串的String列表,如下所示:

  A, 47, 52, 63
  B, 47, 54, 91
  C, 78, 24, 00
  D, 99, 00, 82

请注意,在输入字符串中,日期中没有值,例如对于产品C,2013-05-31和产品D的2013-06-28,输出字符串中的值应默认为00。

因此,在输出字符串中,这些不存在的值被视为00.

如何迭代我的输入集合,其中包含product的日期垂直值以获取输出集合,这是3个日期的产品明智的水平值?

感谢阅读!

4 个答案:

答案 0 :(得分:1)

试试这段代码。您可以轻松地进一步调整它以满足您的确切需求。

    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;


    public class Test002 {

        public static void main(String[] args) throws Exception {
            List<String> input = new ArrayList<String>();

            input.add("2013-07-31,A,47");
            input.add("2013-06-28,A,52");
            input.add("2013-05-31,A,63");

            input.add("2013-07-31,B,47");
            input.add("2013-06-28,B,54");
            input.add("2013-05-31,B,91");

            input.add("2013-07-31,C,78");
            input.add("2013-06-28,C,24");

            input.add("2013-07-31,D,99");
            input.add("2013-05-31,D,82");

            HashSet<Date> dates = new HashSet<Date>();
            HashSet<String> products = new HashSet<String>();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            HashMap<String, Integer> counts = new HashMap<String, Integer>();

            for (String s : input){
                String[] str = s.split(",");
                dates.add(sdf.parse(str[0]));
                products.add(str[1]);
                counts.put(str[0] + "#" + str[1], Integer.parseInt(str[2]));
            }

            for (String p : products){
                for (Date dt : dates){
                    Integer cnt = counts.get(sdf.format(dt) + "#" + p);
                    if (cnt == null){
                        System.out.print("00 ");
                    }else{
                        System.out.printf("%2d ", cnt);
                    }
                }
                System.out.println();
            }
        }

    }

答案 1 :(得分:0)

我认为列表是存储您的值的正确数据结构,因为它是平的。我们对您的域名知之甚少,但如果允许超过三个日期,您最终可能会得到一张包含多个列的表格。

事实上,如果这是一个时间序列,一系列工作表是最好的表示,也许是一个包含聚合期(季度,周,月)和平均值的工作表。所以我按照以下方式为您的域建模:

class TimeSeries {
  String itemDescription;
  Collection<Sample> samples;
}

class Sample {
  Date date;
  BigInteger price;
}

然后我将您输入的字符串列表转换为TimeSeries个对象的列表,您将随后按日期汇总,可能在同一时期有多个样本可用时进行平均,并跳过空的。最后将消化后的结果绘制到Excel工作表上。

答案 2 :(得分:0)

试一试。它首先使用地图然后转换回列表

为您提供所需的输出
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class test1 {

    public static void main(String[] args) {
        List<String> input = new ArrayList<String>();

        input.add("2013-07-31,A,47");
        input.add("2013-06-28,A,52");
        input.add("2013-05-31,A,63");

        input.add("2013-07-31,B,47");
        input.add("2013-06-28,B,54");
        input.add("2013-05-31,B,91");

        input.add("2013-07-31,C,78");
        input.add("2013-06-28,C,24");

        input.add("2013-07-31,D,99");
        input.add("2013-05-31,D,82");

        Map<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();

        for (String s : input) {
            String[] tokens = s.split(",");
            if (!map.containsKey(tokens[1])) {
                ArrayList<String> list = new ArrayList<String>();
                list.add(tokens[2]);
                map.put(tokens[1], list);
            } else {
                ArrayList<String> list = map.get(tokens[1]);
                list.add(tokens[2]);
                map.put(tokens[1], list);
            }
        }

        ArrayList<String> newList = new ArrayList<String>();
        for (Map.Entry<String, ArrayList<String>> entry : map.entrySet()) {
            StringBuilder sb = new StringBuilder();
            sb.append(entry.getKey() + ",");
            for (String s : entry.getValue()) {
                sb.append(s + ",");
            }
            newList.add(sb.toString());
        }

        Collections.sort(newList);

        for (String s : newList) {
            System.out.println(s);
        }
    }
}

输出

A,47,52,63,
B,47,54,91,
C,78,24,
D,99,82,

抱歉,我只是注意到你的注意事项,但我真的无法理解你的意思,所以我不确定如何制作零

答案 3 :(得分:0)

这是我在

的假设下做的
  • 每个日期最多允许一个样本
  • 您的渲染代码决定选择的日期

此方法在渲染之前不会构建中间数据结构,但在从输入列表中读取单元格时会立即绘制单元格:

// Maps items IDs to the row index in the excel sheet
Map<String, Integer> items = new HashMap<>();
// Maps the string representation of the date to the column index in the sheet
Map<String, Integer> columns = new HashMap<>();

public void process(List<String> input) {
  for (String line: input) {
    String[] desc = input.split(",");
    Integer rowIdx = items.get(desc[1]);
    if (rowIdx == null) {
      rowIdx = drawNewItemAndGetRowIndex(desc[1]);
    }
    drawPrice(rowIdx, columns.get(desc[0]), desc[2]);
  }
}

在运行此代码之前,您需要通过放置您感兴趣的日期来初始化Excel工作表和columns地图。注意我使用了日期的字符串表示而不是实际的Date对象,因为您的目的不需要解析。

我将drawNewItemAndGetRowIndex的实现留给了您,但它基本上在Excel工作表中创建了一个新行,在items地图中注册了索引,绘制了项目标题并返回了行索引。