2017-10-11 11 views
1

JSONこのオブジェクトをループするより良い方法はありますか?

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

は私が期待される結果を取得しています。しかし、私はあまりにも多くのループを使用しているような気がします。ここに私のjsfiddleの例があります。

+0

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

+0

'.append()'は配列と連動するので、関数を単一の 'forEach()'ループに減らすことができます。私の解決策を見てください。 –

答えて

1

1つのループに減らす方法はありませんが、2つに減らして可読性を向上させることができます(前の回答で既に述べたように)。

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

プロパティが1つしかないので、外側ループは必要ありません。

最も内側のループは、(また、開口部を追加し、map/join呼び出しの前と後のdivを閉じる)適切なHTMLとそれらをリンクする国の名前を取得するには.map()を使用して.join()で置き換えることができます。あなたが意味的に間違っているul要素、内部で直接div要素を入れた

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>

注意。 div要素が生成された後で、代わりにliを閉じる必要があります。


ここでDOM選択コール数を制限するようにObject.entries().reduce()for-inを置き換える1です。また、テンプレートのリテラルやパラメータの構造化を使用してクリーンアップを行います。

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

あなたのための私のアドバイスは、裸のループを取り除くことでしょう!彼らは実際にコードを読みにくくします。代わりにforEach,mapなどの機能を利用してください。 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>

それが読みやすく見えるん良い命名規則では、ないないそれは?

1

Here's a fiddleこれは

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

私は私より優れた他の2つの答えが好きで、自分のオリジナルのポストよりもパフォーマンスする必要があり、彼らも、よりパフォーマンスの鉱山より見て、小さいループを実行します。

0

jQueryの.append()は、配列を受け入れることができます。これにより、単一のforEachループ(.map())を使用して、国を<li>タグで囲むことができます。

ここではアクションである:

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>

希望私はそれがよりエレガントだか分からないが、コンテンツの両方のピースが単一.append()呼び出しの引数として渡すことができれば次のようになります。

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