5

I have an object named obj that will be used as a basis to create a new array of objects in a certain format.

My base object:

var obj={
  "en": [{
    "faq": "faq",
    "about": "about"
    }],
  "hi": [{
    "faq": "aksar-poochhe-jaane-vaale",
    "about": "hamaare-baare"
    }]    
}

I created a function getObj() which accepts two arguments lang and the base object obj.


SAMPLE SCENARIOS

When I call:

getObj("en", obj);

I should get:

[{
  "url": "/en/faq",
  "links": [
     { lang: 'en', url: '/en/faq' },
     { lang: 'hi', url: '/hi/aksar-poochhe-jaane-vaale' }
   ]
 },
 {
  "url": "/en/about",
  "links": [
     { lang: 'en', url: '/en/about' },
     { lang: 'hi', url: '/hi/hamaare-baare' }
   ]
 }]

When I call:

getObj("hi", obj);

I should get:

 [{
  "url": "/hi/aksar-poochhe-jaane-vaale", 
  "links": [
     { lang: 'en', url: '/en/faq' },
     { lang: 'hi', url: '/hi/aksar-poochhe-jaane-vaale' }
   ]
 },
 {
  "url": "/hi/hamaare-baare",
  "links": [
     { lang: 'en', url: '/en/about' },
     { lang: 'hi', url: '/hi/hamaare-baare' }
   ]
 }]

Below is what I tried:

function getObj(lang, obj){
  var newobj = {};
  newobj['url'] = "/"+ lang +"/"+obj[lang].map(e=>e.faq);
  var s ={lang: lang, url: newobj.url};
  newobj['links']=[s];
  return newobj;
}

1
  • 3
    Is obj.en or obj.hi supposed to be an array? Will it contain more than one object? Because in your sample, it only has one despite being an array. Commented Aug 16, 2019 at 3:55

2 Answers 2

3

Supports obj.en and obj.hi containing more than one object.

Disclaimer: This code does not output an array of objects as originally requested. Rather, it is a object keyed by "page". (This allows the code to be much more efficient.) If you require the exact output, look at the answer below.

var obj={
  "en": [{
    "faq": "faq",
    "about": "about"
    }],
  "hi": [{
    "faq": "aksar-poochhe-jaane-vaale",
    "about": "hamaare-baare"
    }]    
}

function getObj(origLang, obj) {
  if (typeof obj !== 'object') { return false; }
  
  let result = {};
  
  Object.keys(obj).forEach((lang) => { // Loop languages
    obj[lang].forEach((pages) => {
      if (typeof pages !== 'object') { return false; }

      Object.keys(pages).forEach((page) => { // Loop pages
        const url = pages[page];
        
        // Create array if doesn't exist
        if (typeof result[page] == 'undefined') {
          result[page] = {'url': '', 'links': []};
        }
        
        // If original lang, add the url
        if (origLang == lang) { result[page]['url'] = `/${origLang}/${url}`; }
        
        // Add the links
        result[page]['links'].push({
            'lang': lang,
            'url': `/${origLang}/${url}`
        });
      });
    });
  });
  return result;
}

// Output to console.
console.log('The "en" array');
console.log(getObj('en', obj));

console.log('The "hi" array');
console.log(getObj('hi', obj));

Older Version. More readable, but requires looping over the object twice.

var obj={
  "en": [{
    "faq": "faq",
    "about": "about"
    }],
  "hi": [{
    "faq": "aksar-poochhe-jaane-vaale",
    "about": "hamaare-baare"
    }]    
}

function getObj(lang, obj){
  const target = obj[lang];
  let results = [];
      
  target.forEach((pages) => {
   if (typeof pages !== 'object') { return false; }
   Object.keys(pages).forEach((page) => {
      const url = pages[page]; // Get the url
      results.push({
        'url': "/" + lang + "/" + url,
        'links': getLinks(page, obj) // Form the links
      });
    });
  });
  
  return results;
}

function getLinks(page, obj) {
  let links = [];
  if (typeof obj !== 'object') { return false; }
   Object.keys(obj).forEach((lang) => {
      obj[lang].forEach((target) => {
        links.push({
          'lang': lang,
          'url': "/" + lang + "/" + target[page]
        });
      });
  });
  return links;
}

// Output to console.
console.log('The "en" array');
console.log(getObj('en', obj));

console.log('The "hi" array');
console.log(getObj('hi', obj));

Old Javascript:

var obj={
  "en": [{
    "faq": "faq",
    "about": "about"
    }],
  "hi": [{
    "faq": "aksar-poochhe-jaane-vaale",
    "about": "hamaare-baare"
    }]    
}

function getObj(lang, obj){
  var target = obj[lang], 
      results = [];
      
  for (var i = 0; i < target.length; i++) {
    var pages = target[i]; // Get the object {"faq": "faq", "about", "about"}

    for (var page in pages) {
      if (!pages.hasOwnProperty(page)) { continue; }

      var url = pages[page]; // Get the url
      results.push({
            'url': "/" + lang + "/" + url,
            'links': getLinks(page, obj) // Form the links
      });
    }
  }
  
  return results;
}

function getLinks(page, obj) {
  var links = [];
  for (var lang in obj) { // Loop through each language
    if (!obj.hasOwnProperty(lang)) { continue; }
    
    var targets = obj[lang];
    
    for (var i=0; i < targets.length; i++) {
      var target = targets[i];
      links.push({
          'lang': lang,
          'url': "/" + lang + "/" + target[page]
      });
    }
  }
  return links;
}

// Output to console.
console.log('The "en" array');
console.log(getObj('en', obj));

console.log('The "hi" array');
console.log(getObj('hi', obj));

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

2 Comments

Please take the time to understand the above code. If you have any questions, I have an answer. (Maybe not a good one, though ;)
It works by ignoring all but the first element in each array... I think it was still too early to answer.
-1

return can only return one value; the value you're expecting to be returned is a list and isn't contained by anything. This hasn't been a problem (yet) since there isn't any logic for how to handle subsequent values of lang (that have not been explicitly passed).

So you need to do two things:

  1. Find lang keys that weren't used to build the first object and iterate over them to build subsequent items in the list
  2. Pass a single object by containing the list in data structure. Since you're using JS, I'd recommend using an array.

You already have a working function for building the basic nested object, you just need a way to handle the other cases. The below should handle one or more languages; though if a valid lang isn't passed it returns prematurely:

var obj = {
  "en": [{
    "faq": "faq",
    "about": "about"
  }],
  "hi": [{
    "faq": "aksar-poochhe-jaane-vaale",
    "about": "hamaare-baare"
  }]
}

function getOtherKeys(lang, obj) {
  return Object.keys(obj).filter(key => key != lang)
}


// Repurposed your function
function getObj(lang, obj) {
  var newobj = {};
  newobj['url'] = "/" + lang + "/" + obj[lang].map(e => e.faq);
  var s = {
    lang: lang,
    url: newobj.url
  };
  newobj['links'] = [s];

  // my changes below to handle other links
  var keys = getOtherKeys(lang, obj);
  for (var key of keys) {
    newobj['links'].push({
      lang: key,
      url: "/" + key + "/" + obj[key].map(e => e.faq)
    })
  }
  return newobj;
}

// Wrapping your code in an array and handling zeroeth/other keys
function buildObj(lang, obj) {
  var outerObj = [];

  // remove the zeroth key
  var otherKeys = getOtherKeys(lang, obj);

  // Add the primary language
  if (obj[lang]) {
    outerObj.push(getObj(lang, obj));
  } else {
    return;
  }

  // Add all other languages
  for (var key of otherKeys) {
    outerObj.push(getObj(key, obj));
  }
  return outerObj;
}

var obj = {
  "en": [{
    "faq": "faq",
    "about": "about"
  }],
  "hi": [{
    "faq": "aksar-poochhe-jaane-vaale",
    "about": "hamaare-baare"
  }]
}

var en = buildObj("en", obj); // Call array wrapper
console.log(en);

var hi = buildObj("hi", obj);
console.log(hi);

1 Comment

The output isn't similar to the post

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.