使用 Vanilla JS 将 key/value 对对象转换为对象数组
Transform key/value pairs object into array of objects using Vanilla JS
下面是我的对象
var data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
}
下面是我期待的输出
data = [
{ sku: '1', season: 'winter'},
{ sku: '2', season: 'summer'},
{ sku: '3'},
{ sku: '4'},
]
下面是工作脚本,但不容易阅读。大家有什么更好的建议请指教
var data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
}
var arr = Object.entries(data)
.filter(item => item[1] && item[1].length) // remove empty values
.sort((x, y) => y[1].length - x[1].length) // bring lengthy value to first
var final = arr[0][1].map((a, index) =>
arr.reduce((b, acc) => ({
...b,
...(acc[1][index] && { [acc[0]]: acc[1][index] }),
}), {})
);
console.log(final);
function createListOfObjectsFromValuesConfig(config) {
const [
// the entry list with the maximum length `value` list.
primaryEntryList,
// the list of all remaining entry lists.
...listOfSecondaryEntries
] = Object
// get an array of entries, each entry an array itself,
// a tuple of an entry's key and value.
.entries(config)
// sort the array of entry arrays descending by
// comparing the `value` array's `length`properties.
.sort((a, b) => b[1].length - a[1].length);
const [
primaryKey,
primaryValueList,
] = primaryEntryList;
return primaryValueList
.map((primaryValue, primaryIndex) => {
return listOfSecondaryEntries
.reduce((dataItem, [secondaryKey, secondaryValueList]) => {
if (secondaryValueList.hasOwnProperty(primaryIndex)) {
// if possible aggregate the item's
// initially provided base data.
Object.assign(dataItem, {
[secondaryKey]: secondaryValueList[primaryIndex]
});
}
return dataItem;
}, { [primaryKey]: primaryValue }); // create the item's base.
});
}
var data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
};
console.log(
'createListOfObjectsFromValuesConfig(data) ...',
createListOfObjectsFromValuesConfig(data)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
使用 vanilla JS,您可以使用 Array.from()
和 Array.map()
转置(zip)数组。然后映射数组的数组,与原始键组合成对,过滤掉值为undefined
的对。之后,您可以使用 Object.fromEntries()
:
将对数组转换为对象
const zip = (...arr) =>
Array.from({ length: Math.max(...arr.map(a => a.length)) }, (_, i) =>
arr.map(a => a[i])
)
const createObject = obj => {
const keys = Object.keys(obj)
return arr => Object.fromEntries(
keys.map((key, i) => [key, arr[i]])
.filter(([, val]) => val !== undefined)
)
}
const fn = obj => zip(...Object.values(obj)).map(createObject(obj))
const data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
}
const result = fn(data)
console.log(result)
使用 lodash 将数组压缩为一个包含子数组的数组,每个子数组包含一个对象的所有值。然后映射数组的数组,并使用 _.zipObject()
将原始键与值的子数组组合到一个对象,然后 _.omit()
具有 undefined
值的键。
const { omitBy, zipObject, isUndefined, zip } = _
const createObject = obj => {
const keys = Object.keys(obj)
return arr => omitBy(zipObject(keys, arr), isUndefined)
}
const fn = obj => zip(...Object.values(obj)).map(createObject(obj))
const data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
}
const result = fn(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
下面是我的对象
var data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
}
下面是我期待的输出
data = [
{ sku: '1', season: 'winter'},
{ sku: '2', season: 'summer'},
{ sku: '3'},
{ sku: '4'},
]
下面是工作脚本,但不容易阅读。大家有什么更好的建议请指教
var data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
}
var arr = Object.entries(data)
.filter(item => item[1] && item[1].length) // remove empty values
.sort((x, y) => y[1].length - x[1].length) // bring lengthy value to first
var final = arr[0][1].map((a, index) =>
arr.reduce((b, acc) => ({
...b,
...(acc[1][index] && { [acc[0]]: acc[1][index] }),
}), {})
);
console.log(final);
function createListOfObjectsFromValuesConfig(config) {
const [
// the entry list with the maximum length `value` list.
primaryEntryList,
// the list of all remaining entry lists.
...listOfSecondaryEntries
] = Object
// get an array of entries, each entry an array itself,
// a tuple of an entry's key and value.
.entries(config)
// sort the array of entry arrays descending by
// comparing the `value` array's `length`properties.
.sort((a, b) => b[1].length - a[1].length);
const [
primaryKey,
primaryValueList,
] = primaryEntryList;
return primaryValueList
.map((primaryValue, primaryIndex) => {
return listOfSecondaryEntries
.reduce((dataItem, [secondaryKey, secondaryValueList]) => {
if (secondaryValueList.hasOwnProperty(primaryIndex)) {
// if possible aggregate the item's
// initially provided base data.
Object.assign(dataItem, {
[secondaryKey]: secondaryValueList[primaryIndex]
});
}
return dataItem;
}, { [primaryKey]: primaryValue }); // create the item's base.
});
}
var data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
};
console.log(
'createListOfObjectsFromValuesConfig(data) ...',
createListOfObjectsFromValuesConfig(data)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
使用 vanilla JS,您可以使用 Array.from()
和 Array.map()
转置(zip)数组。然后映射数组的数组,与原始键组合成对,过滤掉值为undefined
的对。之后,您可以使用 Object.fromEntries()
:
const zip = (...arr) =>
Array.from({ length: Math.max(...arr.map(a => a.length)) }, (_, i) =>
arr.map(a => a[i])
)
const createObject = obj => {
const keys = Object.keys(obj)
return arr => Object.fromEntries(
keys.map((key, i) => [key, arr[i]])
.filter(([, val]) => val !== undefined)
)
}
const fn = obj => zip(...Object.values(obj)).map(createObject(obj))
const data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
}
const result = fn(data)
console.log(result)
使用 lodash 将数组压缩为一个包含子数组的数组,每个子数组包含一个对象的所有值。然后映射数组的数组,并使用 _.zipObject()
将原始键与值的子数组组合到一个对象,然后 _.omit()
具有 undefined
值的键。
const { omitBy, zipObject, isUndefined, zip } = _
const createObject = obj => {
const keys = Object.keys(obj)
return arr => omitBy(zipObject(keys, arr), isUndefined)
}
const fn = obj => zip(...Object.values(obj)).map(createObject(obj))
const data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
}
const result = fn(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>