2016-11-25 6 views
2

Ich habe eine verschachtelte Array von Objekten wie folgt:dynamisch gruppiert Erstellen von Listen Array von Objekten mit

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"}] 
     ] 

Beachten Sie, dass diese aus einem Array von Objekten erzeugt wurde nach dem Sortieren, Kontinent und anschließend die Länderschlüssel.

Ich möchte eine Liste dynamisch erzeugen, wie folgt (Kontinent und dann Länder) und fügen Sie es zu einem div:

  1. Europa
    • Frankreich
      • Straße ein
    • Deutschland
      • Straße d
  2. Südamerika
    • Brasilien
      • Straße b
      • Straße c

Jedes Mal, wenn die Länder und die Kontinente zurückkehrten, würde dies anders sein, aber das Ergebnis-Array würde in Kontinent, Länderreihenfolge gruppiert werden.

Da ich neu in HTML, CSS und JavaScript bin, kann ich nicht herausfinden, wie man diese Liste dynamisch erstellt. Bisher habe ich es geschafft, eine einzigartige Liste nur der Kontinente erzeugen: ein.

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

dh ich durch die Liste durchlaufen und nur die Mühe, das erste Element zu sehen [Ergebnis [i] [0]) und fügen dies zu einer ungeordneten Liste namens "Kontinent-Liste". Jedes Mal überprüfe ich auch, ob der Name bereits in der ungeordneten Liste existiert und wenn nicht, füge ich nur hinzu.

+1

Es gibt ein paar Syntaxfehler in Ihrem JSON. Sind das wirklich oder ein Tippfehler in der Frage? Kannst du das reparieren? – Taplar

+0

Hier ist kein JSON beteiligt. Bitte lesen Sie die Verwendungsbeschreibung des 'json' Tags. – trincot

Antwort

1

Ich denke, eine Möglichkeit, dies zu tun, ist durch die Objekte in der Array-Schleife und erstellen divs für die Kontinente zur Verfügung, während dafür, dass kein Kontinent einmal erstellt ist mehr als dann noch die gleiche Schleife verwenden Sie so etwas wie

verwenden können
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.... 
    } 
} 

Sorry, ich bin nicht zu jqueryish klingt: D aber wirklich ich hoffe, dass Sie den Umfang erhalten

0
var countries =[[{"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"}]]; 

     var modified = {}; 

     for(var i =0; i<countries.length; i++){ 
      var continent = countries[i]; 
      for(var j =0;j<continent.length;j++){ 
       var country = continent[j]; 
       if(!modified[country.continent]){ 
       modified[country.continent] ={} 
       } 
       if(!modified[country.continent][country.country]){ 
       modified[country.continent][country.country] =[] 
       } 
       modified[country.continent][country.country].push(country); 
     } 
    } 
    var liText = "<ul>"; 
    for (var key in modified) { 
    liText += "<li>"+key + "<ul>"; 
    for (var country in modified[key]){ 
     liText += "<li>"+country + "<ul>"; 
     for(var i=0;i< modified[key][country].length;i++){ 
     liText += "<li>"+modified[key][country][i].name + "</ll>"; 
     } 
     liText += "</ul></li>"; 
    }; 
    liText += "</ul></li>"; 
     }; 
     liText += "</ul>" 

console.log(liText); 

document.getElementById('continent-list').innerHTML = liText; 
+0

Vielen Dank! Das hat funktioniert. – rj91

0

ich lasse Sie die Duplikate behandeln, aber diese sollten Sie die allgemeine Idee geben:

jsFiddle

function displayData(continent, country, street) { 
    console.log(continent + ', ' + country + ', ' + street); 
    var output = $('#output'); 

    var continentLI = document.createElement('li'); 
    var continentTextNode = document.createTextNode(continent); 

    continentLI.appendChild(continentTextNode); 

    var countryUL = document.createElement('ul'); 
    var countryLI = document.createElement('li'); 
    var countryTextNode = document.createTextNode(country); 
    countryLI.appendChild(countryTextNode); 
    countryUL.appendChild(countryLI); 

    var streetUL = document.createElement('ul'); 
    var streetLI = document.createElement('li'); 
    var streetTextNode = document.createTextNode(street); 

    streetLI.appendChild(streetTextNode); 
    streetUL.appendChild(streetLI); 
    countryLI.appendChild(streetUL); 

    continentLI.appendChild(countryUL); 
    output.append(continentLI); 
}; 

$.each(result, function(resultKey, resultValue) { 
    var country = resultValue; 
    $.each(country, function(countryKey, countryValue) { 
    var continent = countryValue.continent; 
    var country = countryValue.country; 
    var street = countryValue.name; 
    displayData(continent, country, street); 
    }); 
}); 
0

Sie könnten flach das Array, sortiert nach Eigenschaften continent, country und street und alle neue Listen erstellen, wenn die Gruppen zu ändern.

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" }]], 
 
    flat = result.reduce(function (r, a) { 
 
     return r.concat(a); 
 
    }, []), 
 
    ol = document.createElement('ol'), 
 
    ul1, ul2; 
 

 
flat.sort(function (a, b) { 
 
    return a.continent.localeCompare(b.continent) || a.country.localeCompare(b.country) || a.name.localeCompare(b.name); 
 
}); 
 

 
flat.forEach(function (a, i, aa) { 
 
    var li; 
 
    if (!i || aa[i - 1].continent !== a.continent) { 
 
     li = document.createElement('li'); 
 
     li.appendChild(document.createTextNode(a.continent)); 
 
     ol.appendChild(li); 
 
     ul1 = document.createElement('ul'); 
 
     ol.appendChild(ul1); 
 
    } 
 
    if (!i || aa[i - 1].country !== a.country) { 
 
     li = document.createElement('li'); 
 
     li.appendChild(document.createTextNode(a.country)); 
 
     ul1.appendChild(li); 
 
     ul2 = document.createElement('ul'); 
 
     ul1.appendChild(ul2); 
 
    } 
 
    li = document.createElement('li'); 
 
    li.appendChild(document.createTextNode(a.name)); 
 
    ul2.appendChild(li); 
 
}); 
 

 
document.getElementById('out').appendChild(ol);
<div id="out"></div>

+0

Das hat wirklich gut funktioniert! Vielen Dank. – rj91

0

Ich denke, die meiste Arbeit getan werden kann, mit der Array-Funktion reduzieren;)

Schritt 1: wir Ihr Array der Struktur umwandeln benötigen Sie:

jetzt ist, wie Ihr continents Datenobjekt loo k wie:

{ 
    "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" 
     } 
    ] 
    } 
} 

Schritt 2:

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

nun das ist, wie $list sollte wie folgt aussehen:

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

wir dieses Objekt in HTML-Elemente mit JQuery konvertieren Schritt 3 Fügen Sie es einfach an das Dokument an, zB:

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

Dies ist nicht die einfachste Anforderung in der Welt, aber auch nicht besonders kompliziert. Es stört mich, dass es so viel Code braucht, um zu lösen. Ich kenne keine Bibliotheken, die dieses Problem trivial, aber zwei, die in sehr praktisch:

Zuerst Ihre Aufzeichnungen übermäßig verschachtelt sind. Um sie rendern zu können, sollten sie geglättet werden.Unders kann dies in einer Zeile tun:

var flat = _.flatten(result); 

Das ist nicht so schwer, im Klar JS ist:

var flat = []; 
result.forEach(sublist => { 
    sublist.forEach(item => flat.push(item)); 
}); 

Aber es ist schön zu können, „es zu tun in einem Zuge“ und Umzug auf.

Dann möchten Sie mehrere Ebenen der Verschachtelung. Underscore hat eine nette groupBy Funktion, aber es ist Single-Level. Es gibt andere Multi-Level-Erweiterungen da draußen, aber das ist mehr Ärger herum. D3 jedoch verwaltet die Verschachtelung sehr einfach:

var nested = d3.nest() 
       .key(d => d.continent) 
       .key(d => d.country) 
       .entries(flat); 

Dann muss die verschachtelte Datenstruktur in HTML gerendert werden. Sie können das direkt mit HTML machen, aber das ist irgendwie unordentlich. Zum Glück haben Browser gute Werkzeuge für die Verwaltung des DOM, auch bekannt als ihre interne Darstellung von HTML. D3 ist gut darin, es zu manipulieren.

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

Das ist nicht besonders kompliziert, wie rekursive Routinen gehen, und es macht aus in gut strukturiert, ziemlich leicht Stil 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 JSFiddle mit der Code ausgeführt wird, und einige optionale CSS zeigt, wie das Ergebnis gestylt werden kann.

Ich wünschte nur, es gäbe einen Weg, dies zu tun, prägnanter.

Verwandte Themen