2017-10-11 1 views
1

JSONGibt es eine bessere Möglichkeit, dieses Objekt zu durchlaufen?

var data = { 
    "countries": { 
    "europe" : [{name: "England", abbr: "en"}, {name: "Spain", abbr: "es"}], 
    "americas" : [{name: "Unites States"}], 
    "asia" : [{name: "China"}] 
    } 
}; 

JS

for (k in data) { 

    for (x in data[k]) { 
    var cObj = data[k][x]; 

    $("#list").append(
     "<li><p>" + x + "</p></li>" 
    ); 

    for (var i=0; i < cObj.length; i++) { 
     $("#list").append(
     "<div> " + cObj[i].name + " </div>" 
    ); 
    } 
    } 
} 

Ich bin das erwartete Ergebnis. Aber ich habe das Gefühl, dass ich zu viele For-Schleifen benutze. Hier ist mein jsfiddle Beispiel.

+0

Blick in [Object.keys()] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Objekt/keys) –

+0

'.append()' arbeitet mit Arrays, so dass es möglich ist, die Funktion auf eine einzige 'forEach()' Schleife zu reduzieren. Siehe meine Lösung. –

Antwort

1

Ich finde keine Möglichkeit, es auf eine Schleife zu reduzieren, aber Sie können es auf zwei reduzieren und die Lesbarkeit verbessern (wie bereits in einer früheren Antwort erwähnt).

$.each(data.countries, function(continent, countries){ 

    $("#list").append(
     "<li><p>" + continent + "</p></li>" 
); 

    $.each(countries, function(index, country){ 
    $("#list").append(
     "<div> " + country.name + " </div>" 
    ); 
    }) 

}) 

Here is an updated jsFiddle.

1

Sie brauchen die äußere Schleife nicht, da es nur eine Eigenschaft gibt.

Die innerste Schleife kann mit .map() bekommen die Namen der Länder und .join() verknüpfen sie mit der richtigen HTML (auch das Hinzufügen des Öffnens und Schließen div vor und nach dem map/join Aufruf) ersetzt werden.

var data = { 
 
    "countries": { 
 
    "europe" : [{name: "England", abbr: "en"}, {name: "Spain", abbr: "es"}], 
 
    "americas" : [{name: "Unites States"}], 
 
    "asia" : [{name: "China"}] 
 
    } 
 
}; 
 

 

 
for (const x in data.countries) { 
 
    const cObj = data.countries[x]; 
 

 
    $("#list").append(
 
    "<li><p>" + x + "</p><div>" + 
 
    cObj.map(c => c.name).join("</div><div>") + 
 
    "</div></li>" 
 
); 
 
}
#list > li > p { 
 
    font-weight: bold; 
 
} 
 

 
#list > li > div { 
 
    padding-left: 10px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<ul id=list></ul>

Beachten Sie, dass div Elemente direkt in einem ul Element setzen wurden, die semantisch falsch ist. Sie sollten stattdessen die li schließen, nachdem die div Elemente generiert wurden.


Hier ist eine, die die for-in mit Object.entries() und .reduce() ersetzt, um die Anzahl von DOM Auswahl Anrufe zu begrenzen. Es verwendet auch Template-Literale und Parameter-Destrukturierung, um Dinge zu bereinigen.

var data = { 
 
    "countries": { 
 
    "europe" : [{name: "England", abbr: "en"}, {name: "Spain", abbr: "es"}], 
 
    "americas" : [{name: "Unites States"}], 
 
    "asia" : [{name: "China"}] 
 
    } 
 
}; 
 

 

 
$("#list").append(
 
    Object.entries(data.countries).reduce((res, [x, a]) => 
 
    res + `<li> 
 
      <p>${x}</p> 
 
      <div>${a.map(c => c.name).join('</div><div>')}</div> 
 
      </li>`, "") 
 
);
#list > li > p { 
 
    font-weight: bold; 
 
} 
 

 
#list > li > div { 
 
    padding-left: 10px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<ul id=list></ul>

1

für Sie Mein Rat nackter Schleifen würde loswerden! Sie machen den Code wirklich schwerer lesbar. Verwenden Sie stattdessen forEach, map usw. Funktionen. Werfen Sie einen Blick auf diesem Schnipsel mit Array.prototype.forEach():

var data = { 
 
    "countries": { 
 
    "europe" : [{name: "England", abbr: "en"}, {name: "Spain", abbr: "es"}], 
 
    "americas" : [{name: "Unites States"}], 
 
    "asia" : [{name: "China"}] 
 
    } 
 
}; 
 

 
Object.keys(data.countries).forEach(function (continent) { 
 
    var countryList = data.countries[continent]; 
 
    $("#list").append("<li><p>" + continent + "</p></li>"); 
 
    countryList.forEach(function (countryObj) { 
 
    $("#list li").append("<div>" + countryObj.name + "</div>"); 
 
    }); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="list"></div>

Mit guter Namenskonvention es besser lesbar aussieht, nicht wahr?

1

Here's a fiddle für Sie. Dies sollte performanter als die ursprüngliche Beitrag sein,

var data = { 
    "countries": { 
    "europe" : [{name: "England", abbr: "en"}, {name: "Spain", abbr: "es"}], 
    "americas" : [{name: "Unites States"}], 
    "asia" : [{name: "China"}] 
    } 
}; 
const continents = Object.keys(data.countries); 
for (let j = 0; j < continents.length; j += 1) { 

    $("#list").append(
     "<li><p>" + continents[j] + "</p></li>" 
    ); 

    let countries = Object.values(data.countries[continents[j]]); 

    for (let i = 0; i < countries.length; i += 1) { 
     $("#list").append(
     "<span> " + countries[i].name + " </span>" 
    ); 
    } 
    } 

Ich mag die beiden anderen Antworten besser als meine, sie sehen sogar performanter als meine und weniger Looping tun.

0

Wir können die Fähigkeit von jQuery .append() nutzen, Arrays zu akzeptieren. Dies ermöglicht uns, eine einzige forEach Schleife (mit einem .map() zu verwenden, um die Länder in <li> Tags zu wickeln).

Hier ist es in Aktion:

var data = { 
 
    "countries": { 
 
    "europe" : [{name: "England", abbr: "en"}, {name: "Spain", abbr: "es"}], 
 
    "americas" : [{name: "Unites States"}], 
 
    "asia" : [{name: "China"}] 
 
    } 
 
}; 
 

 
Object.keys(data.countries).forEach(country => { 
 
    $("#list").append("<li><p>" + country + "</p></li>"); 
 
    $("#list").append(data.countries[country].map(place => "<div> " + place.name + " </div>")); 
 
}); 
 

 
// Using arrow functions here but they could be replaced with standard callback function
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<ul id="list"></ul>

Wenn es gewünscht wird, obwohl ich nicht sicher bin, es eleganter ist, könnten beiden Teile des Inhalts als Argument an einen einzigen .append() Aufruf übergeben werden diese, wie:

Object.keys(data.countries).forEach(country => { 
    $("#list").append(
    "<li><p>" + country + "</p></li>", 
    data.countries[country].map(place => "<div> " + place.name + "</div>") 
); 
}); 
Verwandte Themen