Nodejs 请问有没有处理JSON行列转换的包?

Nodejs 请问有没有处理JSON行列转换的包?

比如:下面JSON, 从列转行 和 行转列,如何快速实现? 尽量保证在O(0)到O(n)的时间复杂度。

[
 {"field":"date","data":[20080102,20080103,20080104,20080105,20080106,20080107,20080108,20080109,20080110]},
 {"field":"x1","data":[1.5916,2.5916,3.5916,3.5916,3.9916,2.5916,9.5916,3.5916,3.5916]},
 {"field":"x2","data":[1.4916,7.5916,1.5916,2.5916,3.116,1.5916,7.5916,0.5916,3.5916]}
 ]

列转行

[
{"date":20080102,"x1":1.5916,"x2":1.4916},
{"date":20080103,"x1":1.5916,"x2":1.4916},
{"date":20080104,"x1":1.5916,"x2":1.4916},
{"date":20080105,"x1":1.5916,"x2":1.4916},
{"date":20080106,"x1":1.5916,"x2":1.4916}
]

评论就不单独回复了:

自己实现的算法 O(m+n),见文件中的 exports.col2row2 函数定义。 https://github.com/bsspirit/ape-algorithm/blob/master/rowcol.js


12 回复

针对您的需求,可以使用 Node.js 的一些内置方法来实现 JSON 列转行和行转列的操作。虽然没有现成的库专门用于这种转换,但我们可以用简洁的方式实现这一功能。

列转行

假设我们有以下列格式的 JSON 数据:

const data = [
    { "field": "date", "data": [20080102, 20080103, 20080104, 20080105, 20080106, 20080107, 20080108, 20080109, 20080110] },
    { "field": "x1", "data": [1.5916, 2.5916, 3.5916, 3.5916, 3.9916, 2.5916, 9.5916, 3.5916, 3.5916] },
    { "field": "x2", "data": [1.4916, 7.5916, 1.5916, 2.5916, 3.116, 1.5916, 7.5916, 0.5916, 3.5916] }
];

我们可以编写一个函数将这些数据转换为行格式:

function colToRow(data) {
    const rows = [];
    const length = data[0].data.length;

    for (let i = 0; i < length; i++) {
        const row = {};
        for (const item of data) {
            row[item.field] = item.data[i];
        }
        rows.push(row);
    }

    return rows;
}

console.log(colToRow(data));

行转列

对于行转列,我们可以使用类似的方法:

function rowToCol(rows) {
    const result = {};

    rows.forEach((row) => {
        Object.keys(row).forEach((key) => {
            if (!result[key]) {
                result[key] = [];
            }
            result[key].push(row[key]);
        });
    });

    // Convert the result object to an array of objects
    const finalResult = [];
    for (const key in result) {
        finalResult.push({ field: key, data: result[key] });
    }

    return finalResult;
}

const rows = [
    { date: 20080102, x1: 1.5916, x2: 1.4916 },
    { date: 20080103, x1: 2.5916, x2: 7.5916 },
    // Add more rows as needed
];

console.log(rowToCol(rows));

这两个函数分别实现了列转行和行转列的功能。它们的时间复杂度为 O(n),其中 n 是数据的长度或数量,符合您的要求。


这个自己写几句代码就搞定啊

trans = (data) ->
	results = []
	for item in data
		for value, index in item.data
			results[index] ?= {}
			results[index]["#{item.field}"] = value
	results

O(m*n)

列转行转过来结果是不是应该是: [ {“date”:20080102,“x1”:1.5916,“x2”:1.4916}, {“date”:20080103,“x1”:2.5916,“x2”:7.4916}, {“date”:20080104,“x1”:3.5916,“x2”:1.4916}, {“date”:20080105,“x1”:3.5916,“x2”:3.4916}, {“date”:20080106,“x1”:2.5916,“x2”:1.4916}. … ]

m+n的怎么实现的?

理论上只能遍历硬转,m * n (field * row),那位 m+n 的不妨贴出来让咱学习学习~

看下lodash这个库,我记得这个库里有实现方法(没看源码),你可以看看

帖子已更新,就不单独回复了。

你们用用大量数据来测试一下,你的这种写法比二楼的写法,花的时间更长,时间复杂度应该是一系统操作所谓的时间吧,eval这种操作的时间复杂度不是O(1)

写了一个速度测试:idy/53eae4fff4b616a82f025533

其实从根本的角度考虑一下,你想做行列变换,几乎要把每个元素都移动一遍才可以,所以每个元素至少都要访问一遍,复杂度至少是 O(n*m) 的。就像你读书,不管你读的是电子书,还是纸质书,先读目录在读正文,或者从后面往前读,你总要每个字都看一遍才算读完的,复杂度最少就是字的个数。 用 eval 只是省去你写代码访问每行的元素,但是 eval 中包含了列数那么多行的赋值代码,如果你把 eval 里面的代码粘贴在 eval 那里,你再看看复杂度,还是 O(n*m) 么。

下面是测试结果:

Speed test
    Scale at: 800 x 800
      ✓ col2row (392ms)
      ✓ col2row2 (454ms)
      ✓ col2row should equal to col2row2 (1ms)
    Scale at: 400 x 1600
      ✓ col2row (315ms)
      ✓ col2row2 (337ms)
      ✓ col2row should equal to col2row2
    Scale at: 200 x 3200
      ✓ col2row (412ms)
      ✓ col2row2 (936ms)
      ✓ col2row should equal to col2row2
    Scale at: 100 x 6400
      ✓ col2row (387ms)
      ✓ col2row2 (264ms)
      ✓ col2row should equal to col2row2
    Scale at: 50 x 12800
      ✓ col2row (331ms)
      ✓ col2row2 (97ms)
      ✓ col2row should equal to col2row2

Complexity test Scale at: 100 x 100 ✓ linear ✓ col2row2 (3ms) ✓ col2row (5ms) Scale at: 200 x 200 ✓ linear ✓ col2row2 (30ms) ✓ col2row (26ms) Scale at: 400 x 400 ✓ linear (1ms) ✓ col2row2 (96ms) ✓ col2row (87ms) Scale at: 800 x 800 ✓ linear ✓ col2row2 (552ms) ✓ col2row (722ms) Scale at: 1600 x 1600 ✓ linear ✓ col2row2 (2672ms) ✓ col2row (1854ms)

30 passing (10s)

楼主有点搞笑了, 掩耳盗铃.

关于行列转换的需求,Node.js 中没有现成的库专门处理 JSON 数据的行列转换。不过我们可以利用一些基础的方法来实现这个功能。以下是如何实现行列转换的示例代码:

列转行

假设输入是一个数组,其中每个对象都有一个 field 和对应的 data 数组。我们可以通过遍历 data 数组,并将每个元素添加到一个新的对象中。

const input = [
    { field: "date", data: [20080102, 20080103, 20080104, 20080105, 20080106, 20080107, 20080108, 20080109, 20080110] },
    { field: "x1", data: [1.5916, 2.5916, 3.5916, 3.5916, 3.9916, 2.5916, 9.5916, 3.5916, 3.5916] },
    { field: "x2", data: [1.4916, 7.5916, 1.5916, 2.5916, 3.116, 1.5916, 7.5916, 0.5916, 3.5916] }
];

function col2row(data) {
    const rows = [];
    for (let i = 0; i < data[0].data.length; i++) {
        const row = {};
        for (const item of data) {
            row[item.field] = item.data[i];
        }
        rows.push(row);
    }
    return rows;
}

console.log(col2row(input));

行转列

将行转列的过程可以看作是将行数据重新组织成列数据。假设输入是一个包含对象的数组,每个对象都具有相同的键值对。

const inputRows = [
    { date: 20080102, x1: 1.5916, x2: 1.4916 },
    { date: 20080103, x1: 2.5916, x2: 7.5916 },
    // 更多行...
];

function row2col(data) {
    const fields = Object.keys(data[0]);
    const result = fields.map(field => ({ field, data: [] }));

    for (const row of data) {
        for (const field of fields) {
            if (field !== 'field') {
                const index = fields.indexOf(field) - 1;
                result[index].data.push(row[field]);
            }
        }
    }

    return result;
}

console.log(row2col(inputRows));

以上代码展示了如何使用基本的 JavaScript 方法实现 JSON 的行列转换。时间复杂度为 O(m * n),其中 m 是字段数量,n 是数据长度。

回到顶部