Pivot/Transform json 个数据列以在 javascript 中创建新行
Pivot/Transform json data columns to create new rows in javascript
我有一个 json
文件,格式如下:
const data = [
{category: "A", country: "UK", name: "United Kingdom", country_id: "01", 2015: 5, 2016: 56, 2017: 10},
{category: "B", country: "UK", name: "United Kingdom", country_id: "01", 2015: 4, 2016: 10, 2017: 10},
{category: "C", country: "UK", name: "United Kingdom", country_id: "01", 2015: 10, 2016: 7, 2017: 45},
{category: "A", country: "PO", name: "Poland", country_id: "02", 2015: 9, 2016: 14, 2017: 10},
{category: "B", country: "PO", name: "Poland", country_id: "02", 2015: 10, 2016: 40, 2017: 0},
{category: "C", country: "PO", name: "Poland", country_id: "02", 2015: 60, 2016: 30, 2017: 74},
{category: "A", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 30, 2016: 20, 2017: 10},
{category: "B", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 15, 2016: 28, 2017: 1},
{category: "C", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 16, 2016: 10, 2017: 2}
]
我想旋转数据以获得以下格式:
- 将
2015
、2016
和 2017
移动到名为 year
的 属性 中
- 从
category
属性 值创建 a
、b
和 c
属性,这些属性将包含不同的值。
- 每个国家和年份有一个 line/object 以及我想保留的任何其他序数类别。
const data = [
{country: "UK", name: "United Kingdom", country_id: "01", year: "2015", "a": 5 , "b": 4, "c": 10},
{country: "UK", name: "United Kingdom", country_id: "01", year: "2016", "a": 56 , "b": 10, "c": 7},
{country: "UK", name: "United Kingdom", country_id: "01", year: "2017", "a": 10 , "b": 10, "c": 45},
{country: "PO", name: "Poland", country_id: "02", year: "2015", "a": 9 , "b": 10, "c": 80},
{country: "PO", name: "Poland", country_id: "02", year: "2016", "a": 14 , "b": 40, "c": 30},
{country: "PO", name: "Poland", country_id: "02", year: "2017", "a": 10 , "b": 0, "c": 74},
{country: "CZ", name: "Czech Republic", country_id: "03", year: "2015", "a": 30 , "b": 15, "c": 16},
{country: "CZ", name: "Czech Republic", country_id: "03", year: "2016", "a": 20 , "b": 28, "c": 1},
{country: "CZ", name: "Czech Republic", country_id: "03", year: "2017", "a": 10 , "b": 1, "c": 2}
我尝试在 map 方法中编写 for 循环,但无法创建 a
、b
和 c
属性。
这不是最好的解决方案,但可以。同时,我为重复项做了一个解决方法。如果其他年份会有新数据,您可以使用 ...rest 参数来初始化年份数组。
let newData = [];
let countries = data.map(({country})=> country)
let categories = data.map(({category})=> category)
let years = [2015,2016,2017];
countries.forEach(country => {
let countryData = data.filter(({country:c}) => c==country);
let yearData = {2015:{},2016:{},2017:{}};
years.forEach(year => {
categories.forEach(category => {
yearData[year][category] = countryData.find(({category:cat}) => cat==category)[year]
})
})
let {name,country_id}= data.find(({country:c}) => c == country);
Object.entries(yearData).forEach(([year,categories]) => {
newData.push({country,name,country_id,year, ...categories})
})
newData = newData.filter((data,i) => i%9<3)
console.log(newData)
})
旋转是在评论的 3 行上完成的 'Rotation'
为了能够做到这一点,我们需要能够访问原始数据集的多行。这里的策略让我们能够做到这一点。
第 1 步。获取唯一 country_ids、年份和类别的列表
有几种方法可以做到这一点,我展示了最容易理解的方法,即转换为Set
(自动删除重复项),然后返回到数组以方便使用.
第 2 步。从简单数组移动到对象
行不是简单地按顺序排列 0...8,而是我们现在将它们放在 3x3 网格中,可按国家和类别寻址。
第 3 步。构建所需的输出
现在在每个国家/地区内,我们可以通过从原始数据的三个不同类别中“提取”今年的值来提取选定年份的所有数据。
const data = [
{category: "A", country: "UK", name: "United Kingdom", country_id: "01", 2015: 5, 2016: 56, 2017: 10},
{category: "B", country: "UK", name: "United Kingdom", country_id: "01", 2015: 4, 2016: 10, 2017: 10},
{category: "C", country: "UK", name: "United Kingdom", country_id: "01", 2015: 10, 2016: 7, 2017: 45},
{category: "A", country: "PO", name: "Poland", country_id: "02", 2015: 9, 2016: 14, 2017: 10},
{category: "B", country: "PO", name: "Poland", country_id: "02", 2015: 10, 2016: 40, 2017: 0},
{category: "C", country: "PO", name: "Poland", country_id: "02", 2015: 60, 2016: 30, 2017: 74},
{category: "A", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 30, 2016: 20, 2017: 10},
{category: "B", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 15, 2016: 28, 2017: 1},
{category: "C", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 16, 2016: 10, 2017: 2}
]
// Step 1. Extract the unique country_id, category Ids and years
const country_ids = Array(...new Set(data.map((x) => x.country_id)));
const categories = Array(...new Set(data.map((x) => x.category)));
const years = ["2015","2016","2017"];
// Step 2. Convert the source data into an object so that you can conveniently read off particular rows, in terms of COUNTRY_ID and CATEGORY
const sourceRows = {};
data.forEach((row) => {
if (!sourceRows[row.country_id]) {
sourceRows[row.country_id] = {};
}
sourceRows[row.country_id][row.category] = row;
});
// You can visualise the output here with this, if you want:
// console.log(sourceRows)
// Step 3. Create destination array, and poke a row into it for each country & year.
const destination = [];
country_ids.forEach((country_id) => {
years.forEach((year) => {
const sourceRow = sourceRows[country_id][categories[0]];
const destRow = {
country_id: country_id,
name: sourceRow.name,
country: sourceRow.country,
year: year,
a: sourceRows[country_id]["A"][year], // Rotation
b: sourceRows[country_id]["B"][year], // Rotation
c: sourceRows[country_id]["C"][year] // Rotation
};
destination.push(destRow);
});
});
console.log(destination);
我有一个 json
文件,格式如下:
const data = [
{category: "A", country: "UK", name: "United Kingdom", country_id: "01", 2015: 5, 2016: 56, 2017: 10},
{category: "B", country: "UK", name: "United Kingdom", country_id: "01", 2015: 4, 2016: 10, 2017: 10},
{category: "C", country: "UK", name: "United Kingdom", country_id: "01", 2015: 10, 2016: 7, 2017: 45},
{category: "A", country: "PO", name: "Poland", country_id: "02", 2015: 9, 2016: 14, 2017: 10},
{category: "B", country: "PO", name: "Poland", country_id: "02", 2015: 10, 2016: 40, 2017: 0},
{category: "C", country: "PO", name: "Poland", country_id: "02", 2015: 60, 2016: 30, 2017: 74},
{category: "A", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 30, 2016: 20, 2017: 10},
{category: "B", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 15, 2016: 28, 2017: 1},
{category: "C", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 16, 2016: 10, 2017: 2}
]
我想旋转数据以获得以下格式:
- 将
2015
、2016
和2017
移动到名为year
的 属性 中
- 从
category
属性 值创建a
、b
和c
属性,这些属性将包含不同的值。 - 每个国家和年份有一个 line/object 以及我想保留的任何其他序数类别。
const data = [
{country: "UK", name: "United Kingdom", country_id: "01", year: "2015", "a": 5 , "b": 4, "c": 10},
{country: "UK", name: "United Kingdom", country_id: "01", year: "2016", "a": 56 , "b": 10, "c": 7},
{country: "UK", name: "United Kingdom", country_id: "01", year: "2017", "a": 10 , "b": 10, "c": 45},
{country: "PO", name: "Poland", country_id: "02", year: "2015", "a": 9 , "b": 10, "c": 80},
{country: "PO", name: "Poland", country_id: "02", year: "2016", "a": 14 , "b": 40, "c": 30},
{country: "PO", name: "Poland", country_id: "02", year: "2017", "a": 10 , "b": 0, "c": 74},
{country: "CZ", name: "Czech Republic", country_id: "03", year: "2015", "a": 30 , "b": 15, "c": 16},
{country: "CZ", name: "Czech Republic", country_id: "03", year: "2016", "a": 20 , "b": 28, "c": 1},
{country: "CZ", name: "Czech Republic", country_id: "03", year: "2017", "a": 10 , "b": 1, "c": 2}
我尝试在 map 方法中编写 for 循环,但无法创建 a
、b
和 c
属性。
这不是最好的解决方案,但可以。同时,我为重复项做了一个解决方法。如果其他年份会有新数据,您可以使用 ...rest 参数来初始化年份数组。
let newData = [];
let countries = data.map(({country})=> country)
let categories = data.map(({category})=> category)
let years = [2015,2016,2017];
countries.forEach(country => {
let countryData = data.filter(({country:c}) => c==country);
let yearData = {2015:{},2016:{},2017:{}};
years.forEach(year => {
categories.forEach(category => {
yearData[year][category] = countryData.find(({category:cat}) => cat==category)[year]
})
})
let {name,country_id}= data.find(({country:c}) => c == country);
Object.entries(yearData).forEach(([year,categories]) => {
newData.push({country,name,country_id,year, ...categories})
})
newData = newData.filter((data,i) => i%9<3)
console.log(newData)
})
旋转是在评论的 3 行上完成的 'Rotation'
为了能够做到这一点,我们需要能够访问原始数据集的多行。这里的策略让我们能够做到这一点。
第 1 步。获取唯一 country_ids、年份和类别的列表
有几种方法可以做到这一点,我展示了最容易理解的方法,即转换为Set
(自动删除重复项),然后返回到数组以方便使用.
第 2 步。从简单数组移动到对象
行不是简单地按顺序排列 0...8,而是我们现在将它们放在 3x3 网格中,可按国家和类别寻址。
第 3 步。构建所需的输出
现在在每个国家/地区内,我们可以通过从原始数据的三个不同类别中“提取”今年的值来提取选定年份的所有数据。
const data = [
{category: "A", country: "UK", name: "United Kingdom", country_id: "01", 2015: 5, 2016: 56, 2017: 10},
{category: "B", country: "UK", name: "United Kingdom", country_id: "01", 2015: 4, 2016: 10, 2017: 10},
{category: "C", country: "UK", name: "United Kingdom", country_id: "01", 2015: 10, 2016: 7, 2017: 45},
{category: "A", country: "PO", name: "Poland", country_id: "02", 2015: 9, 2016: 14, 2017: 10},
{category: "B", country: "PO", name: "Poland", country_id: "02", 2015: 10, 2016: 40, 2017: 0},
{category: "C", country: "PO", name: "Poland", country_id: "02", 2015: 60, 2016: 30, 2017: 74},
{category: "A", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 30, 2016: 20, 2017: 10},
{category: "B", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 15, 2016: 28, 2017: 1},
{category: "C", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 16, 2016: 10, 2017: 2}
]
// Step 1. Extract the unique country_id, category Ids and years
const country_ids = Array(...new Set(data.map((x) => x.country_id)));
const categories = Array(...new Set(data.map((x) => x.category)));
const years = ["2015","2016","2017"];
// Step 2. Convert the source data into an object so that you can conveniently read off particular rows, in terms of COUNTRY_ID and CATEGORY
const sourceRows = {};
data.forEach((row) => {
if (!sourceRows[row.country_id]) {
sourceRows[row.country_id] = {};
}
sourceRows[row.country_id][row.category] = row;
});
// You can visualise the output here with this, if you want:
// console.log(sourceRows)
// Step 3. Create destination array, and poke a row into it for each country & year.
const destination = [];
country_ids.forEach((country_id) => {
years.forEach((year) => {
const sourceRow = sourceRows[country_id][categories[0]];
const destRow = {
country_id: country_id,
name: sourceRow.name,
country: sourceRow.country,
year: year,
a: sourceRows[country_id]["A"][year], // Rotation
b: sourceRows[country_id]["B"][year], // Rotation
c: sourceRows[country_id]["C"][year] // Rotation
};
destination.push(destRow);
});
});
console.log(destination);