1const XEncoding = '__DimX__'
2const ColorEncoding = '__DimColor__'
3/**
4 * 展开并合并视觉通道的维度, 在foldMeasures后合并维度, 所以不需要进行笛卡尔积
5 * @param {Array<Object>} dataset 原始数据集
6 * @param {Array<Object>} dimensions 维度数组,每个维度对象至少包含 id 字段
7 * @param {Object} encoding 编码对象,key为通道名,value为维度id数组
8 * @param {Object} options 配置项
9 * - foldMeasureId: 折叠指标的字段名
10 * - separator: 维度值拼接分隔符
11 * - colorItemAsId: 是否只用颜色项作为 colorId,默认 false
12 * @returns {Object} { dataset, unfoldInfo }
13 */
14function unfoldDimensions(dataset, dimensions, encoding, options) {
15 const { foldMeasureId, separator, colorItemAsId } = options || {}
16
17 const unfoldInfo = {
18 encodingX: XEncoding,
19 encodingColor: ColorEncoding,
20
21 colorItems: [],
22 colorIdMap: {},
23 }
24
25 // 根据 encoding 过滤对应维度
26 const xDimensions = encoding.x ? dimensions.filter(d => encoding.x.includes(d.id)) : []
27 const colorDimensions = encoding.color ? dimensions.filter(d => encoding.color.includes(d.id)) : []
28
29 const colorItemsSet = new Set()
30 const colorIdMap = {}
31
32 for (let i = 0; i < dataset.length; i++) {
33 const datum = dataset[i]
34
35 applyEncoding(XEncoding, xDimensions, datum, separator)
36 applyEncoding(ColorEncoding, colorDimensions, datum, separator)
37
38 const measureId = String(datum[foldMeasureId])
39 const colorItem = String(datum[ColorEncoding])
40 colorItemsSet.add(colorItem)
41 }
42
43 unfoldInfo.colorItems = Array.from(colorItemsSet)
44
45 return {
46 dataset,
47 unfoldInfo,
48 }
49}
50
51/**
52 * 应用编码至数据中, 原地修改 datum
53 * @param {string} encoding 编码字段名
54 * @param {Array<Object>} dimensions 维度数组
55 * @param {Object} datum 单条数据
56 * @param {string} separator 拼接分隔符
57 */
58function applyEncoding(encoding, dimensions, datum, separator) {
59 if (encoding && dimensions.length) {
60 datum[encoding] = dimensions.map(dim => String(datum[dim.id])).join(separator)
61 }
62}
63
64
65const dataset = [
66 { "category": "A", "__MeaId__": "sales", "__MeaName__": "Sales", "__MeaValue__": 100 },
67 { "category": "A", "__MeaId__": "profit", "__MeaName__": "Profit", "__MeaValue__": 30 },
68 { "category": "B", "__MeaId__": "sales", "__MeaName__": "Sales", "__MeaValue__": 200 },
69 { "category": "B", "__MeaId__": "profit", "__MeaName__": "Profit", "__MeaValue__": 50 }
70]
71const dimensions = [
72 { id: 'category'},
73 { id: '__MeaName__'},
74]
75
76const encoding = {
77 x: ['category'],
78 color: ['__MeaName__'],
79}
80
81const options = {
82 foldMeasureId: '__MeaId__',
83 separator: '-',
84 colorItemAsId: false,
85}
86
87const { dataset: unfoldedData, unfoldInfo } = unfoldDimensions(dataset, dimensions, encoding, options)
88
89console.log(unfoldedData)