Reputation: 2102
Below is the object I have
var data = {
sku: ['1', '2', '3', '4'],
color: [],
season: ['winter', 'summer'],
}
Below is the output I'm expecting
data = [
{ sku: '1', season: 'winter'},
{ sku: '2', season: 'summer'},
{ sku: '3'},
{ sku: '4'},
]
Below is the working script but not easy to read. Please suggest if you have any better suggestion.
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);
Upvotes: 0
Views: 520
Reputation: 191976
Using vanilla JS you can transpose (zip) the arrays using Array.from()
with Array.map()
. Then map the array of arrays, combine to pairs with the original keys, and filter out pairs with value that is undefined
. Afterwards you can convert the array of pairs to an object using 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)
With lodash Zip the arrays to an array with sub-arrays that each contains all the values of an object. Then map the array of arrays, and use _.zipObject()
to combine the original keys, with a sub-array of values to an object, and then _.omit()
the keys with undefined
values.
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>
Upvotes: 1
Reputation: 13376
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; }
Upvotes: 1