使用 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>