Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/456.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用对象数组动态创建分组列表_Javascript_Jquery_Html - Fatal编程技术网

Javascript 使用对象数组动态创建分组列表

Javascript 使用对象数组动态创建分组列表,javascript,jquery,html,Javascript,Jquery,Html,我有一个嵌套的对象数组,如下所示: result = [ [{"country":"France","continent":"Europe","name":"street a"}], [{"country":"Brazil","continent":"South America", "name":"street b"},{"country":"Brazil","continent":"South America", "name":"street c"}

我有一个嵌套的对象数组,如下所示:

result = [
           [{"country":"France","continent":"Europe","name":"street a"}],
           [{"country":"Brazil","continent":"South America", "name":"street b"},{"country":"Brazil","continent":"South America", "name":"street c"}],
           [{"country":"Germany","continent":"Europe","name":"street d"}]
         ]
请注意,这是从排序后的对象数组中生成的,先使用大陆键,然后使用国家/地区键

我想动态生成一个列表,如下所示(先是大陆,然后是国家),并将其添加到
div

  • 欧洲
    • 法国
      • a街
    • 德国
      • d街
  • 南美洲
    • 巴西
      • b街
      • c街
  • 每次返回的国家和大陆都会有所不同,但结果数组将按大陆、国家顺序分组

    因为我不熟悉HTML、CSS和JavaScript,所以我不知道如何动态创建此列表。到目前为止,我已经成功地使用以下工具生成了一份唯一的大陆列表:

    for(var i=0;i<result.length;i++){
        if($('#continent-list li').filter(function(){
             return $(this).text() == result[i][0].continent;
        }).length == 0){
             $('#continent-list').append('<li>'+result[i][0].continent+'<ul></ul></li>');
    }
    

    for(var i=0;i我认为一种方法是循环数组中的对象,为可用的大陆创建div,同时确保没有大陆被多次创建,然后仍然使用相同的循环,您可以使用

    for(i=0;i<=results.length;i++){
      if (result[i].continent == continent) //here talking about the present continent in the main loop{
         //code to create new div for the current country....then same procedure for the street part....
        }
    }
    
    for(i=0;i
    var国家=[[{“国家”:“法国”、“大陆”:“欧洲”、“名称”:“街道a”}],{“国家”:“巴西”、“大陆”:“南美洲”、“名称”:“街道b”}{“国家”:“巴西”、“大陆”:“南美洲”、“名称”:“街道c”}],{“国家”:“德国”、“大陆”:“欧洲”、“名称”:“街道d”}];
    var-modified={};
    
    对于(var i=0;i我将让您处理重复项,但这将为您提供总体思路:


    您可以展开数组,按属性
    大陆
    国家
    街道
    排序,并在更改组时构建所有新列表

    var result=[[{“国家”:“法国”、“大陆”:“欧洲”、“名称”:“街道a”}],{“国家”:“巴西”、“大陆”:“南美洲”、“名称”:“街道b”},{“国家”:“巴西”、“大陆”:“南美洲”、“名称”:“街道c”}],{“国家”:“德国”、“大陆”:“欧洲”、“名称”:“街道d”}],
    平坦=结果。减少(函数(r,a){
    返回r.concat(a);
    }, []),
    ol=document.createElement('ol'),
    ul1,ul2;
    平面排序(函数(a,b){
    返回a.continent.localeCompare(b.continent)| | a.country.localeCompare(b.country)| | a.name.localeCompare(b.name);
    });
    flat.forEach(函数(a、i、aa){
    李华;
    如果(!i | | aa[i-1].大陆!==a.大陆){
    li=document.createElement('li');
    li.appendChild(document.createTextNode(a.contraction));
    l.儿童(李);
    ul1=document.createElement('ul');
    其他儿童(ul1);
    }
    如果(!i | | aa[i-1].country!==a.country){
    li=document.createElement('li');
    li.appendChild(document.createTextNode(a.country));
    ul1.儿童(li);
    ul2=document.createElement('ul');
    ul1.附肢儿童(ul2);
    }
    li=document.createElement('li');
    li.appendChild(document.createTextNode(a.name));
    ul2.儿童(li);
    });
    document.getElementById('out').appendChild(ol);

    我认为大部分工作都可以使用array reduce函数完成;)

    步骤1:我们将把您的阵列转换为您需要的结构:

    var result = [
        [{"country": "France", "continent": "Europe", "name": "street a"}],
        [{"country": "Brazil", "continent": "South America", "name": "street b"}, {
            "country": "Brazil",
            "continent": "South America",
            "name": "street c"
        }],
        [{"country": "Germany", "continent": "Europe", "name": "street d"}]
    ];
    
    // fatten the arrays into single array
    var continents = result.reduce(function (a, b) {
        return a.concat(b);
    });
    
    // group by continent
    continents = continents.reduce(function (a, b) {
        if (a[b.continent]) {
            a[b.continent].push(b);
        } else {
            a[b.continent] = [b];
        }
        return a;
    }, {});
    
    // group by country
    Object.keys(continents).forEach(function (continent) {
        continents[continent] = continents[continent].reduce(function (a, b) {
            if (a[b.country]) {
                a[b.country].push(b);
            } else {
                a[b.country] = [b];
            }
            return a;
        }, {});
    });
    
    现在,您的
    大陆
    数据对象应该是这样的:

    {
      "Europe": {
        "France": [
          {
            "country": "France",
            "continent": "Europe",
            "name": "street a"
          }
        ],
        "Germany": [
          {
            "country": "Germany",
            "continent": "Europe",
            "name": "street d"
          }
        ]
      },
      "South America": {
        "Brazil": [
          {
            "country": "Brazil",
            "continent": "South America",
            "name": "street b"
          },
          {
            "country": "Brazil",
            "continent": "South America",
            "name": "street c"
          }
        ]
      }
    }
    
    <ol id="continent-list">
        <li class="continent"><span>Europe</span>
            <ul class="country-list">
                <li><span>France</span>
                    <ul class="street-list">
                        <li>street a</li>
                    </ul>
                </li>
                <li><span>Germany</span>
                    <ul class="street-list">
                        <li>street d</li>
                    </ul>
                </li>
            </ul>
        </li>
        <li class="continent"><span>South America</span>
            <ul class="country-list">
                <li><span>Brazil</span>
                    <ul class="street-list">
                        <li>street b</li>
                        <li>street c</li>
                    </ul>
                </li>
            </ul>
        </li>
    </ol>
    
    步骤2:我们将使用JQuery将此对象转换为html元素:

    // create continents list
    var $list = $('<ol id="continent-list"/>');
    Object.keys(continents).forEach(function (continentName) {
        // create continent
        var $continent = $('<li class="continent"/>').append($("<span/>").text(continentName));
    
        // add countries
        var $countries = $('<ul class="country-list"/>');
        var continent = continents[continentName];
        Object.keys(continent).forEach(function (countryName) {
            var $country = $('<li/>').append($("<span/>").text(countryName));
            // add streets
            var $streets = $('<ul class="street-list"/>');
            var country = continent[countryName];
            country.forEach(function (street) {
                var $street = $('<li/>').text(street.name);
                $streets.append($street);
            });
            $country.append($streets);
            $countries.append($country);
        });
        $continent.append($countries);
    
        // add continent to the list
        $list.append($continent);
    });
    
    步骤3只需将其附加到文档中,例如:

    $("body").append($list);
    

    这不是世界上最简单的需求/请求,但也不是特别复杂。它需要太多的代码才能解决,这让我感到困扰。我知道没有任何库可以让这个问题变得微不足道,但有两个库非常方便:

    首先,您的记录嵌套过多。为了便于渲染,应将其展平。下划线可以在一行中完成此操作:

    var flat = _.flatten(result);
    
    在普通JS中这并不难:

    var flat = [];
    result.forEach(sublist => {
      sublist.forEach(item => flat.push(item));
    });
    
    但能够“一蹴而就”并继续前进是件好事

    然后您需要几个层次的嵌套。下划线有一个很好的
    groupBy
    功能,但它是单层次的。还有其他多层次的扩展,但这更麻烦。不过,D3非常容易管理嵌套:

    var nested = d3.nest()
                   .key(d => d.continent)
                   .key(d => d.country)
                   .entries(flat);
    
    然后需要将嵌套的数据结构呈现为HTML。您可以直接对HTML进行呈现,但这有点混乱。谢天谢地,浏览器有很好的工具来管理DOM,也就是它们对HTML的内部表示。D3非常擅长处理它

    function nested2html(e, n, level) {
      level = level || 0;
      if (typeof e === 'string') e = d3.select(e);
      var list = e.append(level ? 'ul' : 'ol')
                  .attr('class', 'level' + (level+1));
      var leafNode = !n[0].key;
      n.forEach(nitem => {
        if (leafNode) {
          list.append('li').text(nitem.name);
        } else {
          var li = list.append('li');
          li.append('span').text(nitem.key);
          nested2html(li, nitem.values, level + 1);
        }
      });
    }
    
    // now add it to the document
    nested2html('body', nested);
    
    这并不像递归例程那样复杂,它呈现为结构良好、样式非常简单的HTML:

    <ol class="level1">
      <li>
        <span>Europe</span>
        <ul class="level2">
          <li>
            <span>France</span>
            <ul class="level3">
              <li>street a</li>
            </ul>
          </li>
          <li>
            <span>Germany</span>
            <ul class="level3">
              <li>street d</li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <span>South America</span>
        <ul class="level2">
          <li>
            <span>Brazil</span>
            <ul class="level3">
              <li>street b</li>
              <li>street c</li>
            </ul>
          </li>
        </ul>
      </li>
    </ol>
    
    
    
  • 欧洲
    • 法国
      • a街
    • 德国
      • d街
  • 南美洲
    • 巴西
      • b街
      • c街
  • 一个包含运行的代码的示例,以及一些显示如何设置结果样式的可选CSS


    我只希望有一种方法可以更简洁地做到这一点。

    您的json中有一些语法错误。这些是真的还是问题中的输入错误?您能修复吗?这里没有json。请阅读
    json
    标记的用法说明。
    function nested2html(e, n, level) {
      level = level || 0;
      if (typeof e === 'string') e = d3.select(e);
      var list = e.append(level ? 'ul' : 'ol')
                  .attr('class', 'level' + (level+1));
      var leafNode = !n[0].key;
      n.forEach(nitem => {
        if (leafNode) {
          list.append('li').text(nitem.name);
        } else {
          var li = list.append('li');
          li.append('span').text(nitem.key);
          nested2html(li, nitem.values, level + 1);
        }
      });
    }
    
    // now add it to the document
    nested2html('body', nested);
    
    <ol class="level1">
      <li>
        <span>Europe</span>
        <ul class="level2">
          <li>
            <span>France</span>
            <ul class="level3">
              <li>street a</li>
            </ul>
          </li>
          <li>
            <span>Germany</span>
            <ul class="level3">
              <li>street d</li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <span>South America</span>
        <ul class="level2">
          <li>
            <span>Brazil</span>
            <ul class="level3">
              <li>street b</li>
              <li>street c</li>
            </ul>
          </li>
        </ul>
      </li>
    </ol>