I want to map an array of objects, which I got from a json
response of my backend, to an array of arrays, with the first row being an array of headers (titles). I'll use this array to make it downloadable in a csv
file.
我想将我从后端的json响应获得的对象数组映射到数组数组,第一行是标题数组(标题)。我将使用此数组使其可以在csv文件中下载。
Also, I want to keep away a couple of headers / columns that are not really interesting for the end user to have in their csv
file.
另外,我想保留几个头文件/列,这些头文件/列对最终用户来说在他们的csv文件中并不是很有趣。
My code is working fine, but I have the idea that it can be done with more concise code. I'm fine with using ES6 / ES2015, but not really experienced with spread syntax and other ES6 goodies myself, so any suggestions for a better, more modern (functional / reactive?) approach are greatly appreciated.
我的代码工作正常,但我认为可以使用更简洁的代码完成。我很喜欢使用ES6 / ES2015,但我自己并不熟悉扩展语法和其他ES6好东西,所以对于更好,更现代(功能/反应?)方法的任何建议都非常感激。
const originalData = [
{name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
]
let headers = []
const firstRow = originalData[0]
for (var key in firstRow) {
if (firstRow.hasOwnProperty(key)) {
if (!['raw','updated_at'].includes(key)) {
headers.push(key)
}
}
}
const d = originalData.map(function(_, i) {
return headers.map(function(header) {
return originalData[i][header]
}.bind(this))
}.bind(this))
const result = [headers].concat(d)
console.log(result)
8 个解决方案
#1
1
Something like this?
像这样的东西?
const originalData = [
{ name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping' },
{ name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail' },
{ name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing' }
]
const headers = Object.keys(originalData[0]).filter(key => !['raw', 'updated_at'].includes(key));
const d = originalData.map(obj => headers.map(key => obj[key]))
const result = [headers, ...d];
console.log(result)
#2
1
Basically you could use a closure over the filtered keys and map and concat the arrays.
基本上,您可以对过滤后的键使用闭包,并映射和连接数组。
const fn = (array => (keys => [keys].concat(array.map(o => keys.map(k => o[k]))))
(Object.keys(array[0]).filter(k => !['raw','updated_at'].includes(k)))),
data = [{ name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping' }, { name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail' }, { name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing' }],
result = fn(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
#3
0
const originalData = [
{name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
];
const propertiesNeeded = Object.keys(originalData[0]).filter(prop => !['raw', 'updated_at'].includes(prop));
const dataMapped = originalData.map(obj => propertiesNeeded.map(prop => obj[prop]));
const finalArr = [propertiesNeeded, ...dataMapped];
#4
0
This is how I'd do it. I figured if you know which keys you're after then we can make good use of that.
我就是这样做的。我想如果你知道你在追求哪些钥匙,那么我们就可以充分利用它。
const data = [
{name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
]
const desiredKeys = ['name', 'species', 'age', 'skill']
const result = [desiredKeys].concat(data.map(pet => desiredKeys.map(key => pet[key])))
console.log(result)
#5
0
Yours is good. You could simplify the header creation by using Object.keys
你的很好。您可以使用Object.keys简化标头创建
const originalData = [
{name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
]
const headers = Object.keys(originalData[0])
.filter(key => !['raw','updated_at'].includes(key)));
const data = originalData.map(row => headers.map(header => row[header]));
console.log(headers, data);
#6
0
Try with Array#map
used for recreate the array with Object.key
and value
. and new Set()
method user for create the key set value .ignore the repeated one ...
its spread syntax
尝试使用Array#map用于使用Object.key和value重新创建数组。和新的Set()方法用户创建键集值。重复一个...它的扩展语法
const originalData = [
{name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
]
var result = [[...new Set(...originalData.map(a=> Object.keys(a)))]].concat(originalData.map(a=> Object.values(a)))
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
#7
0
A single line of code in an unbroken chain using a filter and reduce.
使用过滤器和减少的完整链中的单行代码。
var unborken = chain => chain.filter((_, i, xx) =>
delete xx[i].updated_at && delete xx[i].raw).reduce((aac, _, i, aa) =>
(i === 0 ? aac.push(Object.keys(aa[i])) && aac.push(Object.values(aa[i])) :
aac.push(Object.values(aa[i])), aac), []);
const originalData = [{
name: 'Gizmo',
species: 'cat',
age: '9',
raw: 'G9e76rd',
updated_at: '1318874398806',
skill: 'sleeping'
},
{
name: 'Benny',
species: 'dog',
age: '3',
raw: '98HDo2h',
updated_at: '1318874392417',
skill: 'chasing tail'
},
{
name: 'Oscar',
species: 'cat',
age: '2',
raw: '9da8Ro1',
updated_at: '1318874390283',
skill: 'meowing'
}
];
console.log(unborken(originalData));
.as-console-wrapper { max-height: 100% !important; top: 0; }
#8
0
I'd like to point out that an object's keys order is not entirely "fixed" by spec.
我想指出一个对象的键顺序并没有完全由规范“修复”。
If your first animal in your originalData
starts with a species
property, your whole table will be formatted in that column order...
如果您的originalData中的第一只动物以物种属性开头,那么您的整个表格将按照该列顺序进行格式化...
Therefore I'd advice you to explicitly define your columns in an array, in which order does matter.
因此,我建议您在数组中明确定义列,其顺序很重要。
Note that in the example below I've swapped the property declaration order of Gizmo. Put this data in your own code and the first column will be species. (at least in my browser it is, I guess it can even differ between browsers?)
请注意,在下面的示例中,我交换了Gizmo的属性声明顺序。将这些数据放在您自己的代码中,第一列将是物种。 (至少在我的浏览器中,我猜它甚至可以在浏览器之间有所不同?)
const data = [
{species: 'cat', name: 'Gizmo', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
]
const getProps = props => obj =>
props.map(k => obj[k]);
const columns = ["name", "species", "age", "skill"];
console.log(
[columns, ...data.map(getProps(columns))]
);
#1
1
Something like this?
像这样的东西?
const originalData = [
{ name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping' },
{ name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail' },
{ name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing' }
]
const headers = Object.keys(originalData[0]).filter(key => !['raw', 'updated_at'].includes(key));
const d = originalData.map(obj => headers.map(key => obj[key]))
const result = [headers, ...d];
console.log(result)
#2
1
Basically you could use a closure over the filtered keys and map and concat the arrays.
基本上,您可以对过滤后的键使用闭包,并映射和连接数组。
const fn = (array => (keys => [keys].concat(array.map(o => keys.map(k => o[k]))))
(Object.keys(array[0]).filter(k => !['raw','updated_at'].includes(k)))),
data = [{ name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping' }, { name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail' }, { name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing' }],
result = fn(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
#3
0
const originalData = [
{name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
];
const propertiesNeeded = Object.keys(originalData[0]).filter(prop => !['raw', 'updated_at'].includes(prop));
const dataMapped = originalData.map(obj => propertiesNeeded.map(prop => obj[prop]));
const finalArr = [propertiesNeeded, ...dataMapped];
#4
0
This is how I'd do it. I figured if you know which keys you're after then we can make good use of that.
我就是这样做的。我想如果你知道你在追求哪些钥匙,那么我们就可以充分利用它。
const data = [
{name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
]
const desiredKeys = ['name', 'species', 'age', 'skill']
const result = [desiredKeys].concat(data.map(pet => desiredKeys.map(key => pet[key])))
console.log(result)
#5
0
Yours is good. You could simplify the header creation by using Object.keys
你的很好。您可以使用Object.keys简化标头创建
const originalData = [
{name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
]
const headers = Object.keys(originalData[0])
.filter(key => !['raw','updated_at'].includes(key)));
const data = originalData.map(row => headers.map(header => row[header]));
console.log(headers, data);
#6
0
Try with Array#map
used for recreate the array with Object.key
and value
. and new Set()
method user for create the key set value .ignore the repeated one ...
its spread syntax
尝试使用Array#map用于使用Object.key和value重新创建数组。和新的Set()方法用户创建键集值。重复一个...它的扩展语法
const originalData = [
{name: 'Gizmo', species: 'cat', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
]
var result = [[...new Set(...originalData.map(a=> Object.keys(a)))]].concat(originalData.map(a=> Object.values(a)))
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
#7
0
A single line of code in an unbroken chain using a filter and reduce.
使用过滤器和减少的完整链中的单行代码。
var unborken = chain => chain.filter((_, i, xx) =>
delete xx[i].updated_at && delete xx[i].raw).reduce((aac, _, i, aa) =>
(i === 0 ? aac.push(Object.keys(aa[i])) && aac.push(Object.values(aa[i])) :
aac.push(Object.values(aa[i])), aac), []);
const originalData = [{
name: 'Gizmo',
species: 'cat',
age: '9',
raw: 'G9e76rd',
updated_at: '1318874398806',
skill: 'sleeping'
},
{
name: 'Benny',
species: 'dog',
age: '3',
raw: '98HDo2h',
updated_at: '1318874392417',
skill: 'chasing tail'
},
{
name: 'Oscar',
species: 'cat',
age: '2',
raw: '9da8Ro1',
updated_at: '1318874390283',
skill: 'meowing'
}
];
console.log(unborken(originalData));
.as-console-wrapper { max-height: 100% !important; top: 0; }
#8
0
I'd like to point out that an object's keys order is not entirely "fixed" by spec.
我想指出一个对象的键顺序并没有完全由规范“修复”。
If your first animal in your originalData
starts with a species
property, your whole table will be formatted in that column order...
如果您的originalData中的第一只动物以物种属性开头,那么您的整个表格将按照该列顺序进行格式化...
Therefore I'd advice you to explicitly define your columns in an array, in which order does matter.
因此,我建议您在数组中明确定义列,其顺序很重要。
Note that in the example below I've swapped the property declaration order of Gizmo. Put this data in your own code and the first column will be species. (at least in my browser it is, I guess it can even differ between browsers?)
请注意,在下面的示例中,我交换了Gizmo的属性声明顺序。将这些数据放在您自己的代码中,第一列将是物种。 (至少在我的浏览器中,我猜它甚至可以在浏览器之间有所不同?)
const data = [
{species: 'cat', name: 'Gizmo', age: '9', raw: 'G9e76rd', updated_at: '1318874398806', skill: 'sleeping'},
{name: 'Benny', species: 'dog', age: '3', raw: '98HDo2h', updated_at: '1318874392417', skill: 'chasing tail'},
{name: 'Oscar', species: 'cat', age: '2', raw: '9da8Ro1', updated_at: '1318874390283', skill: 'meowing'}
]
const getProps = props => obj =>
props.map(k => obj[k]);
const columns = ["name", "species", "age", "skill"];
console.log(
[columns, ...data.map(getProps(columns))]
);