0

I have an object as

var productObj = {
    "product_7": ["level1_group19", "level2_group36"],
    "product_1": ["level1_group19", "level2_group27"],
    "product_8": ["level1_group20"],
    "product_5": ["level1_group19", "level2_group35"],
    "product_2": ["level1_group19", "level2_group27"],
    "product_6": ["level1_group19", "level2_group35"],
    "product_3": ["level1_group19", "level2_group27"],
    "product_4": ["level1_group19", "level2_group27", "level3_group37"],
    "product_10": ["level1_group21"],
    "product_11": ["level1_group21"],
    "product_9": ["level1_group21", "level2_group30"],
    "product_15": ["level1_group24"],
    "product_16": ["level1_group24"],
    "product_13": ["level1_group23"],
    "product_12": ["level1_group22"]
}

How can I build a ul list element as below from the array values of each product using javascript (maybe with jQuery)?

  • level1_group19

    • level2_group36
    • level2_group27
      • level3_group37
    • level2_group35
  • level1_group20

  • level1_group21

    • level2_group30
mplungjan
  • 169,008
  • 28
  • 173
  • 236
tenzin
  • 75
  • 7
  • So `"product_7": ["level1_group19", "level2_group36"]` means that there is a "product_7" which is in "level2_group36" and that itself is in "level1_group19" - is this correct? – VLAZ Jan 20 '21 at 10:04
  • level1_*, level2_* etc are all attributes of a product. – tenzin Jan 20 '21 at 10:08
  • 1
    Then how how does one build this list? What is the relation? How do you know that "level2_group36" should be under "level1_group19"? – VLAZ Jan 20 '21 at 10:11
  • We know that "level2_group36" should be under "level1_group19" because both attributes are present in the same product and the assigned level number (1,2,3 ..) indicates which level of list it should appear. – tenzin Jan 20 '21 at 10:29

2 Answers2

0

As a first step, you can iterate over all properties of the object like that:

let result = {};
for (let property in productObject) {
   if (!productObject.hasOwnProperty(property)) {
      continue;
   }
   // Add groups to result hierarchy
   // Something like:
   result[productObject[property][0]] = {};
}

Further I really get your logic, because the hierarchy in the arrays is not given.

I expect, that you want somehow loop over the array and check the level?

Then you could add it to the final hiearachy in a result object, and iterate finally over this, to display it.

nilosch
  • 143
  • 1
  • 7
  • Hierarchy can be depicted from the assigned level number (1,2,3 ..), which indicates the level of the list it should appear. – tenzin Jan 20 '21 at 10:45
0

I have it working in my case, here it is.

var productObj = {
  "product_7": ["level1_group19", "level2_group36"],
  "product_1": ["level1_group19", "level2_group27"],
  "product_8": ["level1_group20"],
  "product_5": ["level1_group19", "level2_group35"],
  "product_2": ["level1_group19", "level2_group27"],
  "product_6": ["level1_group19", "level2_group35"],
  "product_3": ["level1_group19", "level2_group27"],
  "product_4": ["level1_group19", "level2_group27", "level3_group37"],
  "product_10": ["level1_group21"],
  "product_11": ["level1_group21"],
  "product_9": ["level1_group21", "level2_group30"],
  "product_15": ["level1_group24"],
  "product_16": ["level1_group24"],
  "product_13": ["level1_group23"],
  "product_12": ["level1_group22"]
}


var levelObj = {};


var createNestedObject = function(base, names, value) {
  // If a value is given, remove the last name and keep it for later:
  var lastName = arguments.length === 3 ? names.pop() : false;

  // Walk the hierarchy, creating new objects where needed.
  // If the lastName was removed, then the last object is not set yet:
  for (var i = 0; i < names.length; i++) {
    base = base[names[i]] = base[names[i]] || {};
  }

  // If a value was given, set it to the last name:
  if (lastName) {
    if (Array.isArray(base[lastName])) {
      base = base[lastName].push(value);
    } else {
      base = base[lastName] = [value];
    }
  }

  // Return the last object in the hierarchy:
  return base;
};



var iterateObj = function(obj) {
  Object.entries(obj).forEach(function([key, val]) {
    //Store all usable level tags
    var levelKey = [];

    val.forEach(function(value, index, array) {
      if (value.startsWith('level')) {
        levelKey.push(value);
      }
    });

    //Sort the level
    levelKey.sort();

    createNestedObject(levelObj, levelKey, key);
  });
};


//Make structured Object.
iterateObj(productObj);


var ul = '';
var buildNav = function(obj, level) {
  ul += '<ul class="level_' + level + '">';

  for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
      ul += '<li>' + i; //fil[i]
      if (typeof obj[i] == 'object' && Object.keys(obj[i]).length > 0) {
        level++;
        if (Array.isArray(obj[i]) && obj[i].length > 0) {
          ul += '<ul class="level_' + level + '">';
          obj[i].forEach(function(val, index, arr) {
            ul += '<li>' + val + '</li>';
          });
          ul += '</ul>';
        } else {
          buildNav(obj[i], level);
        }
      }
      ul += '</li>';
    }
  }
  ul += '</ul>';
}

//Prepare the HTML
buildNav(levelObj, 1);

//Make Dom nodes.
$list = $(ul);

$('#prodnav').append($list);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="prodnav"></div>

var productObj = {
  "product_7": ["level1_group19", "level2_group36"],
  "product_1": ["level1_group19", "level2_group27"],
  "product_8": ["level1_group20"],
  "product_5": ["level1_group19", "level2_group35"],
  "product_2": ["level1_group19", "level2_group27"],
  "product_6": ["level1_group19", "level2_group35"],
  "product_3": ["level1_group19", "level2_group27"],
  "product_4": ["level1_group19", "level2_group27", "level3_group37"],
  "product_10": ["level1_group21"],
  "product_11": ["level1_group21"],
  "product_9": ["level1_group21", "level2_group30"],
  "product_15": ["level1_group24"],
  "product_16": ["level1_group24"],
  "product_13": ["level1_group23"],
  "product_12": ["level1_group22"]
}

//To store heirarchy 
var levelObj = {};

//https://stackoverflow.com/questions/5484673/javascript-how-to-dynamically-create-nested-objects-using-object-names-given-by
var createNestedObject = function(base, names) {
  for (var i = 0; i < names.length; i++) {
    base = base[names[i]] = base[names[i]] || {};
  }
};


var iterateObj = function(obj) {
  Object.entries(obj).forEach(function([key, val]) {
    //Store all usable level attributes 
    var levelKey = [];

    val.forEach(function(value, index, array) {
      if (value.startsWith('level')) {
        levelKey.push(value);
      }
    });

    //Sort the level
    levelKey.sort();
    createNestedObject(levelObj, levelKey);
  });
};


//Make structured Object.
iterateObj(productObj);


var ul = '';
var buildNav = function(obj, level) {
  ul += '<ul class="level_' + level + '">';

  for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
      ul += '<li>' + i;
      if (typeof obj[i] == 'object' && Object.keys(obj[i]).length > 0) {
        level++;
        buildNav(obj[i], level);

      }
      ul += '</li>';
    }
  }
  ul += '</ul>';
}

//Prepare the HTML
buildNav(levelObj, 1);

//Make Dom nodes.
$list = $(ul);

$('#prodnav').append($list);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="prodnav"></div>
tenzin
  • 75
  • 7