From 4934374745e92a60b8073195d01a0931b9b1a278 Mon Sep 17 00:00:00 2001 From: ujjaval Date: Wed, 23 Dec 2020 00:20:26 -0800 Subject: [PATCH] Initial Commit --- .gitignore | 2 + README.md | 57 +++++---------- converters/listToObjectConverter.js | 55 ++++++++++++++ converters/objectToListConverter.js | 38 ++++++++++ main.js | 36 ++++++++++ package.json | 16 +++++ .../testListToObjectConverter.js | 71 +++++++++++++++++++ .../testObjectToListConverter.js | 71 +++++++++++++++++++ test/testMain.js | 38 ++++++++++ 9 files changed, 345 insertions(+), 39 deletions(-) create mode 100644 .gitignore create mode 100644 converters/listToObjectConverter.js create mode 100644 converters/objectToListConverter.js create mode 100644 main.js create mode 100644 package.json create mode 100644 test/testConverters/testListToObjectConverter.js create mode 100644 test/testConverters/testObjectToListConverter.js create mode 100644 test/testMain.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..504afef --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +package-lock.json diff --git a/README.md b/README.md index 8e94b53..57e53c0 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,25 @@ -# ONTRAPORT Backend Skills Test +## Object Converter -Hi, Thanks for checking us out +This tool converts the multidimensional container to single list object and vice versa. The code is written in +JavaScript. Mocha and Chai is used for unit testing. -If you're interested in applying for the **Backend Engineer** team a great first step is to complete a brief test to allow us to assess your skills. You will find our Backend Engineer test below. Any language is fine, please note there are **two** questions: +**Steps to run the application:** -1) Write a function that accepts a multi-dimensional container of any size and converts it into a one dimensional associative array whose keys are strings representing their value's path in the original container. +1. Clone/Download the repository. -E.G. +2. Download the dependencies. + ``` + npm install + ``` -``` -{ - 'one': - { - 'two': 3, - 'four': [ 5,6,7] - }, - 'eight': - { - 'nine': - { - 'ten':11 - } - } -} -``` +3. Run the main.js file using node. + ``` + node main.js + ``` -turns into: +**Steps to run unit test for this application:** -``` -{ - 'one/two':3, - 'one/four/0':5, - 'one/four/1':6, - 'one/four/2':7, - 'eight/nine/ten':11 -} -``` - -2) Now write a separate function to do the reverse. - -We want you to fork and then create a pull-reqest against this repository and we'll review it. - -Thanks and good luck! - -Ontraport Careers Team +1. Run the unit test using below command. + ``` + npm test + ``` diff --git a/converters/listToObjectConverter.js b/converters/listToObjectConverter.js new file mode 100644 index 0000000..194fe93 --- /dev/null +++ b/converters/listToObjectConverter.js @@ -0,0 +1,55 @@ +/** + * Convert single array to multidimensional container + * + * @param objList + * @returns new object list + */ +function listToObjectConverter(objList) { + const result = {} + + // loop over the object path + for (const objectPath in objList) { + // split the path into keys + const keyList = objectPath.split('/') + + // create nested object and append the result + let nestedObject = result + let key + + // iterate until second last index + while (keyList.length > 1) { + // poll the keys from the list + key = keyList.shift() + + // check if the last key is index + if (!isNaN(keyList[0])) { + + // check if the key is present or not + if (!nestedObject.hasOwnProperty(key)) { + // create list + nestedObject[key] = [] + } + + // push the value to the list + nestedObject[key].push(objList[objectPath]) + } else { + // check whether the key of the previous object is present or not + // create new object + nestedObject[key] = nestedObject[key] || {} + } + + // update the nested object with the new object + nestedObject = nestedObject[key] + } + + // check whether the last key is not an index. + if (isNaN(keyList[0])) { + // set another key with the appropriate value + nestedObject[keyList[0]] = objList[objectPath] + } + } + + return result +} + +module.exports = listToObjectConverter; diff --git a/converters/objectToListConverter.js b/converters/objectToListConverter.js new file mode 100644 index 0000000..2e61f23 --- /dev/null +++ b/converters/objectToListConverter.js @@ -0,0 +1,38 @@ +/** + * Convert multidimensional container to single array + * + * @param jsonObj + * @param objPath + * @param objList + * @returns {{}} + */ +function objectToListConverter(jsonObj, objPath = null, objList = {}) { + + // check whether the last object is number + // if its number then its the index + if (typeof jsonObj === 'number') { + // append the object + objList = {...objList, [objPath]: jsonObj} + } else if (jsonObj == null) { + // base condition + return objList + } + + // loop over json object + for (const [key, value] of Object.entries(jsonObj)) { + // initially objPath will be null so dont concatenate object path + if (objPath === null) { + // pass the key as object path + objList = objectToListConverter(value, key, objList) + } else { + // append the object path with key + // so that we can get complete path + objList = objectToListConverter(value, `${objPath}/${key}`, objList) + } + } + + // return new objectList + return objList +} + +module.exports = objectToListConverter; diff --git a/main.js b/main.js new file mode 100644 index 0000000..d1db799 --- /dev/null +++ b/main.js @@ -0,0 +1,36 @@ +const objectToListConverter = require("./converters/objectToListConverter"); +const listToObjectConverter = require("./converters/listToObjectConverter"); + +// predefined json object +let jsonObj = { + one: { + two: 3, + four: [5, 6, 7], + }, + eight: { + nine: { + ten: 11, + }, + }, +}; + +/** + * This function converts multidimensional container to single array + * and again converts the single array to multidimensional container. + * + * @param jsonObj + * @returns {*|{}} + */ +function main(jsonObj) { + let list = objectToListConverter(jsonObj) + let newJsonObj = listToObjectConverter(list) + + console.log(list) + console.log(newJsonObj) + + return newJsonObj +} + +main(jsonObj) + +module.exports = main; diff --git a/package.json b/package.json new file mode 100644 index 0000000..f61cc80 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "ontraport", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "mocha --reporter spec --recursive" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "chai": "^4.2.0", + "mocha": "^8.2.1" + } +} diff --git a/test/testConverters/testListToObjectConverter.js b/test/testConverters/testListToObjectConverter.js new file mode 100644 index 0000000..4f0046b --- /dev/null +++ b/test/testConverters/testListToObjectConverter.js @@ -0,0 +1,71 @@ +const expect = require("chai").expect; +const listToObjectConverter = require('../../converters/listToObjectConverter'); + +let objListType1 = { + 'one/two': 3, + 'one/four/0': 5, + 'one/four/1': 6, + 'one/four/2': 7, + 'eight/nine/ten': 11 +} + +describe("Test listToObjectConverter", function () { + it("converts list to object of objListType1", function () { + const newJsonObj = listToObjectConverter(objListType1); + + expect(newJsonObj).to.eql({ + one: { + two: 3, + four: [5, 6, 7] + }, eight: { + nine: { + ten: 11 + } + } + } + ); + }); +}); + +let objListType2 = { + 'one/two': 3, + 'one/four/five/six/seven/0': 8, + 'eight': 11 +} + +describe("Test listToObjectConverter", function () { + it("converts list to object of objListType2", function () { + const newJsonObj = listToObjectConverter(objListType2); + + expect(newJsonObj).to.eql({ + one: { + two: 3, + four: { + five: { + six: { + seven: [8] + } + } + } + }, + eight: 11 + } + ); + }); +}); + +describe("Test listToObjectConverter", function () { + it("converts list to object with empty list", function () { + const newJsonObj = listToObjectConverter({}); + + expect(newJsonObj).to.eql({}); + }); +}); + +describe("Test listToObjectConverter", function () { + it("converts list to object with list parameter as null", function () { + const newJsonObj = listToObjectConverter(null); + + expect(newJsonObj).to.eql({}); + }); +}); diff --git a/test/testConverters/testObjectToListConverter.js b/test/testConverters/testObjectToListConverter.js new file mode 100644 index 0000000..ad8619d --- /dev/null +++ b/test/testConverters/testObjectToListConverter.js @@ -0,0 +1,71 @@ +const expect = require("chai").expect; +const objectToListConverter = require("../../converters/objectToListConverter"); + +let objListType1 = { + one: { + two: 3, + four: [5, 6, 7], + }, + eight: { + nine: { + ten: 11, + }, + }, +} + +describe("Test objectToListConverter", function () { + it("converts object to list of objListType1", function () { + const list = objectToListConverter(objListType1); + expect(list).to.eql({ + 'one/two': 3, + 'one/four/0': 5, + 'one/four/1': 6, + 'one/four/2': 7, + 'eight/nine/ten': 11 + } + ) + }) +}) + +let objListType2 = { + one: { + two: 3, + four: { + five: { + six: { + seven: [8] + } + } + } + }, + eight: 11 +} + +describe("Test listToObjectConverter", function () { + it("converts list to object of objListType2", function () { + const list = objectToListConverter(objListType2); + + expect(list).to.eql({ + 'one/two': 3, + 'one/four/five/six/seven/0': 8, + 'eight': 11 + } + ) + }) +}) + +describe("Test objectToListConverter", function () { + it("converts object to list with empty object", function () { + const list = objectToListConverter({}); + + expect(list).to.eql({}); + }) +}) + +describe("Test objectToListConverter", function () { + it("converts object to list with object parameter as null", function () { + const list = objectToListConverter(null); + + expect(list).to.eql({}); + }) +}) diff --git a/test/testMain.js b/test/testMain.js new file mode 100644 index 0000000..f54a949 --- /dev/null +++ b/test/testMain.js @@ -0,0 +1,38 @@ +const expect = require("chai").expect; +const main = require("../main"); + +let objListType1 = { + one: { + two: 3, + four: [5, 6, 7, 8, 9, 10], + }, + eight: { + nine: { + ten: 11, + }, + }, +} + +describe("Test main", function () { + it("integration test", function () { + const list = main(objListType1); + + expect(list).to.eql(objListType1) + }) +}) + +describe("Test main", function () { + it("integration test with object parameter as empty", function () { + const list = main({}); + + expect(list).to.eql({}); + }) +}) + +describe("Test main", function () { + it("integration test with object parameter as null", function () { + const list = main(null); + + expect(list).to.eql({}); + }) +})