根据for循环中的值对嵌套Json对象进行排序?

时间:2020-03-06 05:33:50

标签: javascript jquery

希望有人可以在这里帮助我,或者至少可以为我指明正确的方向。我花了几个小时试图进行排序,但我迷路了。

下面的代码只是模拟的,我的实际json是使用jquery通过AJAX返回的。我的问题不是排序,而是在嵌套的json对象上排序。

我正在尝试根据成本对json输出进行排序。 (从最低成本到最高成本),我的尝试失败了,因此无法排序。我不断得到“排序”是不确定的。

任何帮助将不胜感激,或者如果您能在这里指出我做错了什么,将不胜感激。

var json = '{"shipping_method":{"ups":{"title":"United Parcel Service","quote":{"12":{"code":"ups.12","title":"UPS 3 Day Select","cost":117.3,"tax_class_id":"0","text":"$117.30"},"13":{"code":"ups.13","title":"UPS Next Day Air Saver","cost":242.52,"tax_class_id":"0","text":"$242.52"},"14":{"code":"ups.14","title":"UPS Next Day Air Early A.M.","cost":279.95,"tax_class_id":"0","text":"$279.95"},"03":{"code":"ups.03","title":"UPS Ground","cost":54.62,"tax_class_id":"0","text":"$54.62"},"02":{"code":"ups.02","title":"UPS 2nd Day Air","cost":177.31,"tax_class_id":"0","text":"$177.31"},"01":{"code":"ups.01","title":"UPS Next Day Air","cost":248.08,"tax_class_id":"0","text":"$248.08"}},"sort_order":"","error":""}}}';

    /* 

    This doesnt work and returns undefined. 
    
    json["shipping_method"]["quote"].sort(function(a, b) {
        return a['cost'] > b['cost'];
      });

    // I found this example, but also didn't work.
    custSort = (prop1, prop2 = null, direction = 'asc') => (e1, e2) => {
    const a = prop2 ? e1[prop1][prop2] : e1[prop1],
    b = prop2 ? e2[prop1][prop2] : e2[prop1],
    sortOrder = direction === "asc" ? 1 : -1
     return (a < b) ? -sortOrder : (a > b) ? //sortOrder : 0;
    };      

   json.sort(custSort("quote", "cost", "desc"));*/


json = JSON.parse(json);

for (var i in json["shipping_method"]) {

  // EDIT::  I want the sorting to occur here if possible. 

  for (j in json["shipping_method"][i]["quote"]) {


  //EDIT::  I want to keep this for loop, but with the results sorted by cost 

    console.log(json["shipping_method"][i]["quote"][j]["cost"]);

  }

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

5 个答案:

答案 0 :(得分:3)

将对象转换为排序数组

可以将对象展平,以便在深层对象中对其进行迭代时将父键包含在其中。在此答案编辑历史中可以找到一个较早的示例。由于诸如quote-id之类的信息不重要,因此已将其删除。

下面是一个使用Object.values的示例,它遍历一个对象并仅返回该对象值的数组(丢弃键)。然后可以按照cost的顺序对值进行排序。

const json = JSON.parse(getData());

for (let method in json["shipping_method"]) {
  // cache
  let quotes = json['shipping_method'][method]['quote']
  
  // convert object to array and sort
  let sortedQuotes = Object.values(quotes).sort((a, b)=>a.cost-b.cost);
  
  console.log(sortedQuotes)
}


/* Dummy Data */
function getData() {
  return '{"shipping_method":{"ups":{"title":"United Parcel Service","quote":{"12":{"code":"ups.12","title":"UPS 3 Day Select","cost":117.3,"tax_class_id":"0","text":"$117.30"},"13":{"code":"ups.13","title":"UPS Next Day Air Saver","cost":242.52,"tax_class_id":"0","text":"$242.52"},"14":{"code":"ups.14","title":"UPS Next Day Air Early A.M.","cost":279.95,"tax_class_id":"0","text":"$279.95"},"03":{"code":"ups.03","title":"UPS Ground","cost":54.62,"tax_class_id":"0","text":"$54.62"},"02":{"code":"ups.02","title":"UPS 2nd Day Air","cost":177.31,"tax_class_id":"0","text":"$177.31"},"01":{"code":"ups.01","title":"UPS Next Day Air","cost":248.08,"tax_class_id":"0","text":"$248.08"}},"sort_order":"","error":""}}}';
}
.as-console-wrapper {
  max-height: 100vh !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

每种运输方式的报价

这假定需要引用ID(可能放在一行中);否则,可以使用Object.values代替Object.entries来简化此操作(以及其他更改)。

忽略output函数的作用。这是一个简单的示例,它不能确保正确的单元顺序,并且还具有许多其他限制和漏洞。它仅用于说明排序后原始quote数据仍然可用。

const data = JSON.parse(getData());

for (let method in data.shipping_method) {
  output({row: method}, {class:'capitalize'})
  
  // cache
  let quotes = data.shipping_method[method].quote
  let sortContent = Object.entries(quotes);
  let sortedQuotes = sortContent.sort((a,b)=>a[1].cost-b[1].cost).map(i=>i[0]);
  
  for (let quoteId of sortedQuotes){
    let quoteInfo = quotes[quoteId];
    output({cell: quoteInfo})
  }
}

/* Dummy Data */
function getData() {
  return '{"shipping_method":{"ups":{"title":"United Parcel Service","quote":{"12":{"code":"ups.12","title":"UPS 3 Day Select","cost":117.3,"tax_class_id":"0","text":"$117.30"},"13":{"code":"ups.13","title":"UPS Next Day Air Saver","cost":242.52,"tax_class_id":"0","text":"$242.52"},"14":{"code":"ups.14","title":"UPS Next Day Air Early A.M.","cost":279.95,"tax_class_id":"0","text":"$279.95"},"03":{"code":"ups.03","title":"UPS Ground","cost":54.62,"tax_class_id":"0","text":"$54.62"},"02":{"code":"ups.02","title":"UPS 2nd Day Air","cost":177.31,"tax_class_id":"0","text":"$177.31"},"01":{"code":"ups.01","title":"UPS Next Day Air","cost":248.08,"tax_class_id":"0","text":"$248.08"}},"sort_order":"","error":""}}}';
}

/* Really simple output for demo purpose */
function output(data, options={}){

  if ('row' in data){
    let $col = $('<td></td>', options).html(data.row)
    let $row = $('<tr></tr>').append($col);
    $('tbody').append( $row )
  }
  
  else if ('cell' in data){
    let $row = $('<tr></tr>')
    for( let key in data.cell ){
      let $col = $('<td></td>', options).html(data.cell[key])
      $row.append($col)
    }
    $('tbody').append( $row )
  }
  
}
.capitalize {
  text-transform: uppercase;
}

td {
  min-width: 5rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<table>
  <thead></thead>
  <tbody></tbody>
</table>

答案 1 :(得分:1)

您的对象可以具有任意数量的属性,如果将对象放入数组中,则可以选择按所需的对象属性,数字或字符串进行排序。

var item = JSON.parse(json).shipping_method.ups.quote;

使用 Object.values()获取JSON对象的值数组,然后使用 slice()方法复制JSON对象的数组,而不仅仅是参考。

var byCost = Object.values(item).slice(0);

最后,您可以对该对象数组使用排序功能。

byCost.sort(function(a,b) {return a.cost - b.cost});

var json = '{"shipping_method":{"ups":{"title":"United Parcel Service","quote":{"12":{"code":"ups.12","title":"UPS 3 Day Select","cost":117.3,"tax_class_id":"0","text":"$117.30"},"13":{"code":"ups.13","title":"UPS Next Day Air Saver","cost":242.52,"tax_class_id":"0","text":"$242.52"},"14":{"code":"ups.14","title":"UPS Next Day Air Early A.M.","cost":279.95,"tax_class_id":"0","text":"$279.95"},"03":{"code":"ups.03","title":"UPS Ground","cost":54.62,"tax_class_id":"0","text":"$54.62"},"02":{"code":"ups.02","title":"UPS 2nd Day Air","cost":177.31,"tax_class_id":"0","text":"$177.31"},"01":{"code":"ups.01","title":"UPS Next Day Air","cost":248.08,"tax_class_id":"0","text":"$248.08"}},"sort_order":"","error":""}}}';
var item = JSON.parse(json).shipping_method.ups.quote;
var byCost = Object.values(item).slice(0);
byCost.sort(function(a,b) {return a.cost - b.cost});
console.log(byCost)

答案 2 :(得分:0)

似乎您在这里未找到正确的路径...查看您发布的JSON,您应该尝试对shipping_method.ups.quote进行排序,同样值得注意的是shipping_method.ups.quote是一个对象,并且必须转换为数组才能调用.sort as this method lives on the Array prototype.

这可以通过几种方式完成,但是Object.values()是其中一种方式。

答案 3 :(得分:0)

您可以尝试以下操作,

json = JSON.parse(json);
  let item = json.shipping_method.ups.quote,
    temp = [];
  for (let key in item) {
    temp.push(item[key]);
  }
  temp.sort((x, y) => x.cost - y.cost);
  json.shipping_method.ups.quote = temp;

将对象转换为数组,然后排序;

答案 4 :(得分:0)

如我所见,您的问题是按成本对对象进行排序,因为它们的键应保持不变,

尝试一下,

var json = '{"shipping_method":{"ups":{"title":"United Parcel Service","quote":{"12":{"code":"ups.12","title":"UPS 3 Day Select","cost":117.3,"tax_class_id":"0","text":"$117.30"},"13":{"code":"ups.13","title":"UPS Next Day Air Saver","cost":242.52,"tax_class_id":"0","text":"$242.52"},"14":{"code":"ups.14","title":"UPS Next Day Air Early A.M.","cost":279.95,"tax_class_id":"0","text":"$279.95"},"03":{"code":"ups.03","title":"UPS Ground","cost":54.62,"tax_class_id":"0","text":"$54.62"},"02":{"code":"ups.02","title":"UPS 2nd Day Air","cost":177.31,"tax_class_id":"0","text":"$177.31"},"01":{"code":"ups.01","title":"UPS Next Day Air","cost":248.08,"tax_class_id":"0","text":"$248.08"}},"sort_order":"","error":""}}}';

var json = JSON.parse(json);
let data = []
for(var i in json.shipping_method.ups.quote){
    data.push(json.shipping_method.ups.quote[i])
    data.sort((a,b) => a.cost - b.cost);
}

这将像以前一样创建这些键

let final = {} ;
data.forEach(el => final[el.code.split('.')[1]] = el);

最后用最新的报价单更新qoute:

json.shipping_method.ups.quote = final;