【问题标题】:Sorting JSON Object排序 JSON 对象
【发布时间】:2011-09-03 02:28:18
【问题描述】:

尝试对 JSON 对象进行排序时遇到问题。基本上,人们可以以任何随机顺序将产品添加到我们的订单中,但它在摘要中显示的顺序需要是我们希望它们的位置(而不是他们选择它们的顺序),所以这就是我需要排序的原因'id'(或者我们稍后会按 'pos' 字段排序)

基本上,我需要按 id 升序排序。 1,2,103 而不是 2,103,1

我似乎遇到了问题,因为单个对象的索引是数字(或者只是它们存在的事实......)。

我需要按照 array.sort(function(a,b){ return a.id-b.id });但我认为这不起作用,因为 1,它不是一个数组(它是一个对象),而 2,它有那些讨厌的索引(我需​​要我的代码的另一部分)......

有什么想法吗????

var products = {
    "2": {
        "id": "2",
        "price": "119",
        "quantity": "1",
        "thumb": "img\/store\/comp-08n.png"
    },
    "103": {
        "id": "103",
        "price": "109",
        "quantity": "1",
        "thumb": "img\/store\/basketballhoop.png"
    },
    "1": {
        "id": "1",
        "price": "309",
        "quantity": "1",
        "thumb": "img\/store\/comp-08.png"
    }
};

【问题讨论】:

  • 对象本质上是无序的(即,属性包没有“排序”);你期望的结果是什么?
  • 我认为他使用的是一个对象作为关联数组,而不是他真正想要的“稀疏数组”。
  • 使用对象数组。此外,检查 underscore.js。挺好看的。

标签: javascript jquery json sorting object


【解决方案1】:

您的订单需要多少件商品?您可以安全地对 Javascript 数组中的 10'000 个项目进行排序,而不会出现很多速度问题。为什么不使用真正的数组呢?

您甚至可以向其注入自定义属性,大致类似于

var products = [...];

products.findById = function(id) {
   for (var i=0, len=this.length; i<len; i++) {
      if (id == this[i].id) return this[i];
   }
   return null;
};

alert( products.findById(103).price );   // -> 119

并添加预定义的排序器,例如

products.sortById = function() {
    this.sort(function(a,b) {
        return a.id - b.id;
    });
};

products.sortById();   // sort array by product id

** 编辑 **

在你的 PHP 端,你可能有类似的东西:

$products = array(
    2 => array( 'id' => 2, ... ),
    103 => array( 'id' => 103, ... ),
    1 => array( 'id' => 1, ... ),
);

// get a JSON array
$jsonArray = json_encode(array_values($products));

将返回您需要的内容。

** 注意 **

在数组中添加新项目时,不应显式设置索引。使用数组的push函数,比如

products.push({id:123, price:200.49, quantity:1, thumb:'/path/to/file'});

删除一个项目有点棘手,但是,类似于:

products.removeById = function(id) {
   for (var i=0, len=this.length; i<len; i++) {
      if (id == this[i].id) return this.splice(i, 1)[0];
   }
   return null;
};

products.removeById(123);    // -> returns the removed element! or null if nothing was removed

查看演示 here(使用 Chrome 开发工具进行控制台输出)。

【讨论】:

  • 最多可能有 20 个……嗯,PHP 是否具有将关联数组转储到 JS 数组中的功能,还是我只做一个?目前我只是在使用 json_encode
  • php 有 json_encode() 如果所有索引都是整数,则返回一个 Javascript 数组(参见手册)
  • 非常感谢 Yanick,非常有帮助 :) 我使用您的分拣机让它工作,并让 PHP 将其转储为对象数组而不是对象对象
  • 很高兴我能帮上忙。查看最新的修改以了解更多详情(如果您还没有这样做)
  • 再次感谢!我只是注意到 findBy 是我如何找到适当的索引而不是设置它(在大声笑之前没有下沉)。您是否会说在开始时将我的数组排序为正确的索引(使用 for products.length newarr[products[i].id] = products[i])之间的性能差异,以便我可以通过 product[id] 访问更好还是比每次更改产品时都运行 findById 函数更糟糕(速度方面)?
【解决方案2】:

在 JavaScript 和 JSON 中有两种类型的集合:

  1. 键/值映射(对象) - 无序集合和
  2. 数组 - 索引/值映射(数组) - 有序集合。

根据定义,只能对数组进行排序。使用数组。

【讨论】:

  • 那么,例如,我如何在不知道输出顺序的情况下访问 id 的价格?例如我不能只做产品[1][1] 是价格或其他什么...:\
  • @Benno 你只会做 product[1].price
  • 所以我的数组看起来像这样? var products = [1:{price:109,name:'Thing'}];因为这似乎不起作用.. 很奇怪,我之前从未创建过这样的数组,哈哈:\
  • @Benno,使用这个:var a = []; a[1] = {price:109,name:'Thing'}; 等。大多数 JS 实现使用所谓的稀疏数组,因此您可以创建带有“孔”的数组。
  • “稀疏数组”与使用对象完全一样。它的存储方式相同,处理方式相同,length 不再适合使用。那么你没有将数组用作数组。
【解决方案3】:

递归解决方案,但不处理数组,javascript

var alphabetizeJSON = function(obj){
    var key,
        array = [],
        stringifiedValuesObj = {},
        jsonKeyVal = "",
        i,
        keyName;

    for (key in obj) {
        if (typeof obj[key] === "object"){
            stringifiedValuesObj[key] = "" + alphabetizeJSON(obj[key]);
        } else {
            obj[key] = obj[key].replace(/\"/gi,'\\\"');
        }
        array.push(key);
    }

    array.sort();

    for (i = 0; i < array.length; i++){
        keyName = array[i];
        jsonKeyVal += '"' + keyName + '": ';
        jsonKeyVal += stringifiedValuesObj[keyName] ? stringifiedValuesObj[keyName] : '"' + obj[keyName] + '"';
        if (i < array.length - 1 ) {
            jsonKeyVal += ',';
        }
    }

    return '{ ' + jsonKeyVal + '}';
};

【讨论】:

  • 我收到以下错误:ReferenceError: orderJSON is not defined
  • 谢谢,已修复。我更改了函数的名称
【解决方案4】:

查看JSONArrays。他们可能是你需要的。 http://json.org/java/

【讨论】:

    【解决方案5】:

    确实,您应该能够使用数组而不是对象来完成这项工作,这将解决您的很多困难。

    如果你不能这样做,你可以将对象转换成一个数组来给它排序......像这样:

    var a = []
    for (var p in obj) {
      a[+p] = obj[p]
    }
    

    如果你不能这样做,你可以按照你想要的顺序动态地将信息添加到页面中(以下是一个坏主意)......

    for (var i = 0; i < 10000; i++) {
      if (obj[i] !== undefined) {
        add_to_page(obj[i])  //define this somewhere
      }
    }
    

    【讨论】:

    • 嗯,这确实有效,哈哈,赢了!虽然我意识到它会浪费资源(尽管它们是最小的),所以我会先尝试将它转换为数组,但如果我厌倦了,我会这样做:)
    猜你喜欢
    • 2018-07-08
    • 2017-06-07
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    相关资源
    最近更新 更多