0

I have a list of object in array

var myLevel = ['sub', 'topic', 'type'];

var myCollection = new Array();
myCollection.push({sub: 'Book 1', topic: 'topic 1', type: 'mcq'});
myCollection.push({sub: 'Book 1', topic: 'topic 1', type: 'mcq'});
myCollection.push({sub: 'Book 1', type: 'fib', topic: 'topic 2'});
myCollection.push({sub: 'Book 1', topic: 'topic 1', type: 'mtf'});
myCollection.push({sub: 'Book 1', topic: 'topic 1', type: 'mcq'});
myCollection.push({sub: 'Book 2', type: 'mcq', topic: 'topic 1'});
myCollection.push({sub: 'Book 2', topic: 'topic 1', type: 'mcq'});
myCollection.push({sub: 'Book 2', topic: 'topic 1', type: 'mcq'});

I want to convert these things in to proper list with ul and li, also the levels of listing is dependent on myLevel variable.

  • Book 1
    • topic 1
      • mcq
      • mtf
    • topic 2
      • fib
  • Book 2
    • topic 1
      • mcq

Every section has a unique children, no duplicate childrens.

I tried this code, but it generates duplicate children

var dom="<ul>";
var used = new Array();
var currentItems = new Array(myLevel.length);
var lastJ = -1;

for(var i=0; i<myCollection.length; i++)
{
    var con = false;
    for(var k=0; k<used.length; k++){
        if(compareObjects(used[k], myCollection[i]))
            con = true;
    }
    if(!con){
        for(var j=0; j<myLevel.length; j++){
            if(currentItems[j] !== myCollection[i][myLevel[j]]){
                if(lastJ !== -1){
                    for(var l=0; l<lastJ-j; l++){
                        dom+="</ul></li>";   
                    }
                }
                for(var l=j+1; l<currentItems.length; l++)
                    currentItems[l] = "";
                currentItems[j] = myCollection[i][myLevel[j]];
                dom+="<li>"+currentItems[j]+(j<myLevel.length-1?"<ul>":"");
                lastJ = j;
            }
        }
        used.push(myCollection[i]);
    }
}
dom+="</ul>";
$('body').html(dom);

function compareObjects(obj1, obj2){
    if(obj1.length != obj2.length)
        return false;
    for(var el in obj1){
        if(obj2[el] === undefined)
            return false;
        if(obj1[el] !== obj2[el])
            return false;
    }
    return true;
}

I get the following result

  • Book 1
    • topic 1
      • mcq
    • topic 2
      • fib
    • topic 1
      • mtf
  • Book 2
    • topic 1
      • mcq

Here book 1 has got two topic 1. which is incorrect. i need only 1 topic 1. and that topic 1 should have both mcq and mtf.

JSFiddle link

Thanks

2 Answers 2

1

Use the code given below:

var $out;
$(document).ready(function()
{

    for(var i=0; i<myCollection.length; i++)
    {
        $out = $('#out');
        for(var j=0; j<levelTree.length; j++)
        {
            var itemName = myCollection[i][levelTree[j]];
            var level = j;

            /**********************************************************/


                var $con;
                if($out.children().eq(0).length == 0)
                {
                    $con = $('<ul></ul>');
                    $con.append('<li>'+ itemName + '</li>');
                    $out.append($con);
                }
                else
                {
                    var flag = $out.children().eq(0).children().filter(function(i, e)
                    {
                         return (this.childNodes[0].textContent == itemName);
                    });
                    console.log(flag.length);
                    if(flag.length == 0)
                    {
                        $out.children().eq(0).append('<li>' + itemName + '</li>');
                    }
                }

                var ele = $out.children(0).eq(0).children().filter(function(i, e)
                {
                    return (this.childNodes[0].textContent == itemName);
                }).get();
                $out = $(ele);


            /**********************************************************/
        }
    }
});

JSFiddle link

I hope it helps.

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

Comments

1

Sounds like you could do a reduce:

var newCollection = myCollection.reduce(function (p, v) {
    var book = p[v.sub];
    // if we haven't seen this book before...
    if (!book) {
        book = p[v.sub] = {};
    }
    // if we haven't seen this topic before...
    if (!book[v.topic]) book[v.topic] = [];
    // if we haven't seen this type before...
    if (book[v.topic].indexOf(v.type) !== -1) book[v.topic].push(v.type);
    return p;
}, {})

Which outputs:

{
  "Book 1": {
    "topic 1": [
      "mcq"
      "mtf"
    ],
    "topic 2": [
      "fib"
    ]
  },
  "Book 2": {
    "topic 1": [
      "mcq"
    ]
  }
}

Here's a working fiddle: http://jsfiddle.net/kL1kud34/1/

3 Comments

thanks jivings, but the duplicate nodes are incorrect. Topic 1 has three mcq, there should be only 1.
@AshokShah There you go, I added an indexOf into the mix.
Thanks this answer is helpful. But the nodes should be dependent on myLevel variable, for nesting levels. Any idea would be a great help

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.