0

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);

7
  • 1
    “Expecting” of which code? Familiarize yourself with how to access and process nested objects, arrays or JSON and how to create objects and use the available static and instance methods of Object and Array. Commented Sep 6, 2021 at 21:57
  • 3
    @w3debugger ... As I know SO any somehow reasonable attempt would have spared you the downvotes. But just dropping the Q without showing an effort did the opposite. There are people that are really strict about that. But they are mostly willing too, taking the vote back after the OP does edit the Q accordingly. Commented Sep 6, 2021 at 22:09
  • 4
    Indeed, right now this question is "gimme the code". Showing your effort would've prevented that. Still, it is interesting that you think posting your attempt would've resulted in more downvotes :/ Commented Sep 6, 2021 at 22:16
  • 1
    @w3debugger ... out of curiosity, the example code you did provide in the end, was this your 1st approach? And if so, why did you not post it? And since it also does its job, where was your actual problem? The only suggestion i have ... write human readable code (readable after some month too), for yourself and others. Commented Sep 6, 2021 at 23:35
  • 1
    @PeterSeliger I knew how to get the result but as you can see it is not readable. That's why I asked if anyone can suggest less and clear code. I wrote the code after posting it. AFAIK this platform is not only expert guys posting perfect answers and experts posting answers. I was really disappointed by seeing negative impression but in the end learnt the mindset majority has... BTW Thanks :) Commented Sep 6, 2021 at 23:52

2 Answers 2

1

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; }

Sign up to request clarification or add additional context in comments.

Comments

1

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.