Interview question that stumped me

Long story short, I got rocked on a code pairing interview question and still can’t find a great way to solve it. Any thoughts? I knew that manipulating objects were a weak point, guess it’s time to revisit objects.
Question is as follows:
Given an input = [
{foo: 10, bar: 20},
{foo: 12, bar: 30}
]

Write a function that results in this output = {foo: [10, 12], bar: [20,30]}

The keys foo and bar are unknown.

Hints are that Object.keys() will be needed and a double for loop is likely.

well, with the method you get an array of the keys, so now they are no more unknown, but can be referenced as needed

and now you have two arrays to deal with: the array of keys, and the array of objects

what could you do with them?

What if you were given this?

// put all of the properties in the the objArr array into 
// the corresponding properties of testObj
function test(objArr) {
  const testObj = {
     foo: [],
     bar: []
  }
}

If you know how you would do that, then how could you create testObj if it wasn’t given to you?

With the following function I am able to get the required output. I am struggling with how to incorporate Object.keys now. If I loop through Object.keys(input[i]) and assign to an array, I get two arrays of keys: keys = [ [foo, bar], [foo, bar] ]. I could then reduce the keys array down to find unique values but I have a hunch that there is a better way to do this that would bypass the reduce.

function convert(input){
    const foo = []
    const bar = []
    let obj ={}
for(let i = 0; i < input.length; i++){
     foo.push(input[i]['foo'])
     bar.push(input[i]['bar'])
     }
  obj['foo'] = foo
  obj['bar'] = bar
return obj //returns {foo: [10, 12], bar: [20, 30]}
}

Step one completed, I am able to get the values of both foo and bar into the ObjArr with this:

function test(input) {
  const testObj = {
     foo: [],
     bar: []
  }
  for(let i = 0; i < input.length; i++){
  testObj['foo'].push(input[i]['foo'])
  testObj['bar'].push(input[i]['bar'])
  }
}//testObj = {
     foo: [10, 12],
     bar: [20, 30]

I am still trying to figure out the construction of the ObjArr using Object.keys

1 Like

What if you had to create the same result, but instead of testObj you were given

function test(input) {
   const props = ['foo', 'bar'];
}

Hi,

Can you take a look to the output please.
Is it possible you make a typing mistake?
You wrote:

output = 
{foo: [10, 12], 
bar: [12,30]
} 

but correctly:

 output = 
{foo: [10, 12], 
bar: [20,30]
}

???
If you made typing mistake here is my solution:

Summary
"use strict";
/*
Given an input = [
{foo: 10, bar: 20},
{foo: 12, bar: 30}
]

Write a function that results in this output = {foo: [10, 12], bar: [20, 30]}

The keys foo and bar are unknown.

Hints are that Object.keys() will be needed and a double for loop is likely.
*/

const myOutput = input => {
    const output = {};
    input.forEach(obj => {
        for (let key in obj) {
            if (!(output[key])) output[key] = [];
        }
        
        for (let key in obj) {
            output[key].push(obj[key]);
        }
        
    });
    return output;
}



const input = [
    {foo: 10, bar: 20},
    {foo: 12, bar: 30}
];

const unknownKeys = [
    {unknown: 10, nobody: 20},
    {unknown: 12, nobody: 30}
];

console.log(myOutput(input));
console.log(myOutput(unknownKeys));

I did not find any way to build the output in the same for loop but I also did not used Object.keys().

If your output is not a mistake, then I have to modify the function…

Sorry, Yes I made a mistake. I edited the original post.

Looks like this works! I am still trying to wrap my head around it and also figure out using Object.keys()

Ok,
than focus to the IMPORTANT information: The keys are unknown.
So do not use in your code

foo: anything

or

obj["foo"] = anything

or

foo.push(input[i]['foo'])

because the keys are unknown.
All of the above solutions are incorrect.

ps. edit: From now you can find the way to use Object.keys() too…
I’ll be curious will you find a way to build output with too loop only… Till now I have no idea…

Using Object.keys:

const transform = input => input.reduce((obj, elem) => {
  Object.keys(elem).forEach(prop => {
    obj[prop] = !obj.hasOwnProperty(prop)
      ? [ elem[prop] ]
      : [ ...obj[prop], elem[prop] ];
  });
  return obj;
}, {});

Thank you for RandellDawson

Here is the modified function with two loops only:

Summary
const myOutput = input => {
    const output = {};
    input.forEach(obj => {
        for (let key in obj) {
            if (!(output[key])) {
                output[key] = [];
                output[key].push(obj[key]);
            } else output[key].push(obj[key]);
        }
    });
    return output;
}

Whenever you see repeated line, there is a room for improvement:

if (!output[key]) output[key] = [];
output[key].push(obj[key]);
1 Like