【问题标题】:Convert array objects to nested ul li Elements将数组对象转换为嵌套的 ul li 元素
【发布时间】:2014-11-28 12:05:25
【问题描述】:

我有一个数组中的对象列表

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'});

我想用 ul 和 li 将这些东西转换成适当的列表,列表的级别也取决于 myLevel 变量。

  • 书 1
    • 主题 1
      • mcq
      • mtf
    • 主题 2
      • 纤维
  • 书 2
    • 主题 1
      • mcq

每个部分都有一个唯一的孩子,没有重复的孩子。

我尝试了这段代码,但它会生成重复的孩子

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;
}

我得到以下结果

  • 书 1
    • 主题 1
      • mcq
    • 主题 2
      • 纤维
    • 主题 1
      • mtf
  • 书 2
    • 主题 1
      • mcq

这里第 1 册有两个主题 1。这是不正确的。 我只需要 1 个主题 1。主题 1 应该同时具有 mcq 和 mtf。

JSFiddle link

谢谢

【问题讨论】:

    标签: javascript jquery html arrays object


    【解决方案1】:

    使用下面给出的代码:

    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

    希望对你有帮助。

    【讨论】:

      【解决方案2】:

      听起来你可以做一个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;
      }, {})
      

      哪些输出:

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

      这是一个有效的小提琴:http://jsfiddle.net/kL1kud34/1/

      【讨论】:

      • 感谢 jivings,但重复节点不正确。题目1有3个mcq,应该只有1个。
      • @AshokShah 好了,我添加了一个indexOf
      • 感谢这个答案很有帮助。但是节点应该依赖于 myLevel 变量,用于嵌套级别。任何想法都会有很大帮助
      猜你喜欢
      • 1970-01-01
      • 2018-11-30
      • 2013-05-26
      • 2023-04-02
      • 2012-05-05
      • 1970-01-01
      • 2015-03-26
      • 2019-01-31
      相关资源
      最近更新 更多