Array to Object for loop type error - JS

Hello all,

I’m working on a repl.it program for Code Platoon.
The directions are:

The variable tableData below represents data as it might appear in a table or spreadsheet. The first array contains column names and the rest of the arrays are rows of data. Write a function convertTable that converts the data in a nested array like tableData to an array of objects that matches the output below. Your function should work for any array formatted like tableData, meaning it should always use the first array given as the keys and the rest of the arrays as values.

For example:

const tableData = [
  ["first_name", "last_name", "city", "state"],
  ["Elisabeth", "Gardenar", "Toledo", "OH"],
  ["Jamaal", "Du", "Sylvania", "OH"],
  ["Kathlyn", "Lavoie", "Maumee", "OH"]
]

convertTable(tableData) 

// The return is below
[
  { first_name : "Elisabeth", last_name : "Gardenar", city: "Toledo", state : "OH" },
  { first_name : "Jamaal", last_name : "Du", city: "Sylvania", state : "OH" },
  { first_name : "Kathlyn", last_name : "Lavoie", city: "Maumee", state : "OH" }
]

My program:

// Write your convertTable function here

const tableData = [
  ["first_name", "last_name", "city", "state"],
  ["Elisabeth", "Gardenar", "Toledo", "OH"],
  ["Jamaal", "Du", "Sylvania", "OH"],
  ["Kathlyn", "Lavoie", "Maumee", "OH"]
];

var row =[];

function convertTable(arr) {
  for (i = 0; i < arr.length; i++) {
    var fname = arr[i+1][0], lname = arr[i+1][1], city = arr[i+1][2], state = arr[i+1][3];
    console.log(arr[0][0] + " : \"" + fname + "\", " + arr[0][1] + " : \"" + lname + "\", " + arr[0][2] + " : \"" + city + "\", " + arr[0][3] + " : \"" + state + "\"");
         row = (arr[0][0] + " : \"" + fname + "\", " + arr[0][1] + " : \"" + lname + "\", " + arr[0][2] + " : \"" + city + "\", " + arr[0][3] + " : \"" + state + "\"");
  }    
  return row;
}
convertTable(tableData);

The console error:
Native Browser JavaScript

first_name : “Elisabeth”, last_name : “Gardenar”, city : “Toledo”, state : “OH”
first_name : “Jamaal”, last_name : “Du”, city : “Sylvania”, state : “OH”
first_name : “Kathlyn”, last_name : “Lavoie”, city : “Maumee”, state : “OH”
TypeError: Cannot read property ‘0’ of undefined
at convertTable:14:27
at eval:20:1
at eval
at new Promise

Thanks for your help in advance!!!

// This probably isn't exactly right but it is kind of close and I had fun trying
//It runs but the result is ordered a little differently than I expected
// So hopefully it helps a little bit

const tableData = [
  ["first_name", "last_name", "city", "state"],
  ["Elisabeth", "Gardenar", "Toledo", "OH"],
  ["Jamaal", "Du", "Sylvania", "OH"],
  ["Kathlyn", "Lavoie", "Maumee", "OH"]
];

function convertTable(arr) {
let keys=[];
let result = [];
//loop through the first element to get the key names you will use when you create your objects
for (let keyLoop = 0; keyLoop < tableData[0].length; keyLoop++) {
  keys.push(tableData[0][keyLoop]);  
}

//Loop for each record (Skipping index of 0 since that was keys)
for (let dataLoop = 1; dataLoop < tableData.length; dataLoop++) {
  let obj =  {}; //
  //Assign values to each key
  for (let item in keys) {
  obj[keys[item]] = tableData[dataLoop][item];
  }
  result.push(obj); //update the array with the value for the currrent record
}
  return result; //return the final array
}
convertTable(tableData);

Thanks. That’s pretty creative and I’m having fun with this exercise too. I’ll play around with your suggestion and see if I can get it to work as expected.

However, I wasn’t looking for a solution, rather an explanation as to why i’m getting the type error on my variables. Do you know why?

you created a string, they want an object
your row is NOT an object

you are almost there, that’s for sure, but you need to make it an object, not a string

after that try to make it work with arrays of any length, that I think also you are missing, you will need to tweak a few things there

Thanks. ieahleen, this is helpful. I will work on returning an Object. I did try using i values in every key value pair, but when I do that I get an infinate loop warning. That’s why I chose to use hard coded key value pairs. Do you have any tips or references I can read through on how to turn an array into an object. I’ve tried assign and create, but I cant use the array key value pairs or variable to create the Object (or at least I don’t know how). Thanks

@klbellware The user @davidmarccram has already given you an example of creating an object from an array. Try to use the same logic.

Thanks, Randell, I appreciate the suggestion. However, I need the values to appear in exact order (first name: username, last name: user Lname, city: city name, state: state name). In his example, they don’t always show in the correct order. Any suggestions on that?

The only way to preserve property order in a JavaScript object is to create the object manually. What difference does it make to your application? An object is an object. It does not care about the order of properties.

If you are truly concerned about order then you could use a Map which will iterate over the key/value pairs in the order you inserted them.

Thanks again Randell. Technically speaking it wouldn’t matter, but the instructions tell me the data needs to be displayed in that order. I’m still going to try to pass the exercise with the example provided though and see how it goes, but first I have to get the result to return correclty. One of the reasons I tried to avoid using @davidmarccram example is because I am learning and really would like explination and suggestion, so I can figure out what I’m doing wrong, not answers.

Either way, I’ve used his example but I’m getting an empty array returned. Here is my code:

// Write your convertTable function here

const tableData = [
  ["first_name", "last_name", "city", "state"],
  ["Elisabeth", "Gardenar", "Toledo", "OH"],
  ["Jamaal", "Du", "Sylvania", "OH"],
  ["Kathlyn", "Lavoie", "Maumee", "OH"]
];

var rowObj = {};

function convertTable(arr) {
  let keys = [];
  let result = [];
  
  for (let key = 0; key < tableData[0].length; key++) {
    keys.push(tableData[0][key]);
    console.log(keys);
  }
  
  for (let user = 1; user < keys.length; user++) {
    let tableObj = {};
    
    for (let item in keys) {
      tableObj[keys[item]] = tableData[user][item];
    }
    result.push[tableObj];
    console.log(tableObj);
  }
  return result;
}
convertTable(tableData);

and here is the console log window of results:

Native Browser JavaScript
   
[ 'first_name' ]
[ 'first_name', 'last_name' ]
[ 'first_name', 'last_name', 'city' ]
[ 'first_name', 'last_name', 'city', 'state' ]
{ first_name: 'Elisabeth',
  last_name: 'Gardenar',
  city: 'Toledo',
  state: 'OH' }
{ first_name: 'Jamaal',
  last_name: 'Du',
  city: 'Sylvania',
  state: 'OH' }
{ first_name: 'Kathlyn',
  last_name: 'Lavoie',
  city: 'Maumee',
  state: 'OH' }
=> []
   

I did try moving the let tableObj = {} outside of the function so it would be available outside of the loop and returing the tableObj, but this only returns one user. I also must return an array of objects not just an array.

I read your problem description again and realize the final return value is an array of objects and not just an object.

The reason @davidmarccram’s code does not work, is that he did not call the push method correctly. See if you can figure out what is wrong about his syntax. Once that is fixed, it will work.

Ah thanks! He used brackets instead of parentheses. I changed that and the array of all 3 objects did return correctly. Thanks to all three of you for your continued help!

When I run the tests to pass the assignment though it fails and here is what I get:

Failed tests
handles_given_input
Your convertTable function didn’t produce the expected output
Expected $[0].first_name = ‘Kathlyn’ to equal ‘Elisabeth’. Expected $[0].last_name = ‘Lavoie’ to equal ‘Gardenar’. Expected $[0].city = ‘Maumee’ to equal ‘Toledo’.
More info
handles_custom_input

My assumption is that they want me to return the objects using Object dot notation instead of returning it in an array. Does that sound right?

Oh and the brackets was my mistake not his.

Not sure what you mean by “using Object dot notation instead of returning it in an array”. According to what the instructions showed as the expected value to return, once you fixed the parentheses issue, your function would be returning what they expect.

Yes it does look like it’s returing what’s expected, but the assignment test says it is not what’s expected. What I meant is maybe printing the lines using result.values or Object.values()

I suppose I’ll just go back to what I had in the beginning and work from there since this is not what the assignment wants.

I do appreciate everyone’s help,

FYI - Since you already created a function that does what the instructions stated, I will show you more concise way to do it using map and reduce.

function convertTable ([ propNames, ...data ]) {
  return data.map(values => values
    .reduce((obj, value, i) => (
      { ...obj, [propNames[i]]: value }
    ), {})
  );
}

Thanks for teaching me Randell. I discovered the reason the assignment wasn’t passing. I had moved let tableObj = { } outside of the function when I was getting an empty array. The empty array was due to the brakets after push instead of parentheses. Then I forgot to move it back . That was causing the loop to produce the same user each time through the loop instead of individule users. This clears the first part of my assignment. The second part just needs me to create another object that will produce similar results with different data. I know how to do that. So all is good! Thanks again.

Glad you figured it out. It was really bugging me that something was a little off in the example I posted earlier. The discussion on this was really helpful to me too. Thanks, everyone.

1 Like