尝试对自定义JavaScript对象进行排序

时间:2010-07-30 00:48:31

标签: javascript arrays sorting object

我不太擅长JS,但到目前为止还活了下来。我正在创建一个复杂的JS对象,并希望对其进行排序。对象的结构如下所示:

cart.attributes = [
  {
    Attribute,
    Value
  }
  ...
];

我正在创建一个独特的属性,告诉我3个由冒号任意分隔的东西:
(产品ID):(产品数量迭代器):(属性名称)
产品QTY迭代器只是意味着,如果我有3个相同的产品,那么凌晨3点我在谈论属性。然后每个属性都有一个值。

问题正如您从打印输出中看到的那样,没有任何组织。我想首先按(产品ID),然后是(QTY Iterator)对这些结果进行排序,然后按字母顺序按(名称)排序。

这是使用以下方法打印出来的对象,然后打印出结果。

使用打印结果的代码

$.each(cart.attributes, function(attr, value) {
  console.log("Attr: "+attr);
  console.log("Value: "+value);
});

结果

«Attr» 46913872:2:Size
«Value» 10
«Attr» 46913872:2:Hollow-to-Hem
«Value» 57"
«Attr» 46913872:1:Hips
«Value» 34"
«Attr» 46913872:2:Bust
«Value» 34"
«Attr» 46913872:2:Dress Color (hex)
«Value» #FFFFFF
«Attr» 46913872:2:Rush Cut
«Value» Super Rush Cut - 6 weeks
«Attr» 46913872:1:Extra Length
«Value» 5"
«Attr» 46913872:2:Hips
«Value» 34"
«Attr» 46913872:1:Waist
«Value» 29"
«Attr» 46913872:2:Waist
«Value» 23"
«Attr» 46913872:2:Dress Color (name)
«Value» White
«Attr» 46913872:1:Rush Cut
«Value» Super Rush Cut - 6 weeks
«Attr» 46913872:1:Sash Color (name)
«Value» Lipstick
«Attr» 46913872:2:Sash Color (hex)
«Value» #000000
«Attr» 46913872:1:Size
«Value» 14
«Attr» 46913872:1:Hollow-to-Hem
«Value» 58"
«Attr» 46913872:1:Bust
«Value» 35"
«Attr» 46913872:1:Sash Color (hex)
«Value» #B6064C
«Attr» 46913872:1:Dress Color (hex)
«Value» #F9C8D0
«Attr» 46913872:1:Dress Color (name)
«Value» Tea Rose
«Attr» 46913872:2:Extra Length
«Value» 5"
«Attr» 46913872:2:Sash Color (name)
«Value» Black

5 个答案:

答案 0 :(得分:4)

从下面的评论中我可以更清楚地了解对象是什么。

假设对象看起来像这样:

cart.attributes = {
    '46913872:2:Size' : 10,
    '46913872:2:Hollow-to-Hem' : 57
    // ...
}

由于它不是数组,因此无法排序。但是你可以将其分类打印出来。

在普通的旧javascript中你可以这样做:

// First get all keys:
var keys = [];
for (var n in cart.attributes) {
    if (cart.attributes.hasOwnProperty(n)) {
        keys.push(n);
    }
}

// now sort the keys:
keys.sort(function(a,b){
    attr_a = a.split(':');
    attr_b = b.split(':');

    // sort by product ID:
    if (parseInt(attr_a[0],10) < parseInt(attr_b[0],10)) return -1;
    if (parseInt(attr_a[0],10) > parseInt(attr_b[0],10)) return 1;
    // sort by quantity:
    if (parseInt(attr_a[1],10) < parseInt(attr_b[1],10)) return -1;
    if (parseInt(attr_a[1],10) > parseInt(attr_b[1],10)) return 1;
    // finally sort by name:
    if (attr_a[2] < attr_b[2]) return -1;
    if (attr_a[2] > attr_b[2]) return 1;
    return 0;
})

// now print out the object in key-sorted-order:
for (var i=0; i<keys.length; i++) {
    console.log("Attr: "+keys[i]);
    console.log("Value: "+cart.attributes[keys[i]]);
}

答案 1 :(得分:3)

您应该能够基于对象属性对对象数组进行排序,方法是编写自定义排序函数,如下所示:

function customSortByPID(a,b) {
  if (a.ProductID > b.ProductID)
  {
      return 1;
  }
  else if (a.ProductID < b.ProductID)
  {
      return -1;
  }
  return 0;
}

其中ProductID是对象的属性。你会这样称呼它:

  myArray.sort(customSortByPID);

这至少应该让你开始研究如何编写自定义排序函数。请注意,JavaScript不是强类型的,可能会导致意外的排序行为(将int视为字符串)。

**免责声明**我没有测试上述任何一项,它只是在我的头顶。

答案 2 :(得分:3)

首先,理解对象的结构真的很难。这是它的样子吗?

[
  {  "46913872:2:Size" : 10 },
  {  "46913872:2:Hollow-to-Hem": 57},
  {  "46913872:1:Hips" : "34"}, ...
]

看起来你想要它排序

[
  {  "46913872:1:Hips" : "34"}, // all ids are the same here, but this index is 1
  {  "46913872:2:Hollow-to-Hem": 57}, // index is 2 but Hollow comes before Size
  {  "46913872:2:Size" : 10 },
]

如果我了解您的对象结构,以下解决方案是有效的。就像ThatSteveGuy所说,你可以将比较器传递给你的排序方法。由于对象太复杂了,这就是你要做的事情

attributes.sort(function(a, b){
  // Make sense of your objects a and b. See the inner function defined below
  var newA = improveObject(a);
  var newB = improveObject(b);

  if (newA.id > newB.id) { return 1; }
  if (newA.id < newB.id) { return -1; }
  // id is the same, check index
  if (newA.index > newB.index) { return 1; }
  if (newA.index < newB.index) { return -1; }
  // index is the same, check name
  if (newA.name > newB.name) { return 1; }
  if (newA.name < newB.name) { return -1; }
  // it's the same thing 
  return 0;

  // Turns {  "46913872:2:Size" : 10 }
  // into {id: 46913872, index: 2, name: "Size", value: 10}
  function improveObject(obj) {
    for (var key in obj) {
      var pieces = key.split(":");
      return {
        id: parseInt(pieces[0]),
        index: parseInt(pieces[1]),
        name: pieces[2],
        value: obj[key];
      };
    }
  }
});

但是,这个对象真的没有意义。我会敦促你重新思考它的结构。即使我没有完全理解你的对象(你应该列出对象的实际json),这个例子告诉你所有你需要知道的关于js排序的事情。

答案 3 :(得分:1)

如果要将多个值放在由分隔符分隔的字符串中,那么您首先忽略了创建对象的重点。结构应该是,

cart.attributes = [
    {
        attributes: {
            id: "46913872",
            quantityIterator: 2,
            name: "Dress Color"
        },
        value: "57",
    },
    // repeat for each product
];

创建一个从编码字符串创建对象的函数是微不足道的。用':'拆分字符串并分别记录每个部分。

function makeProduct(key, val) {
    var parts = key.split(':');

    var attrs = {};
    attrs.productId = parts[0];
    attrs.quantityIterator = parts[1];
    attrs.name = parts[2];

    return { attributes: attrs, value: val};
}

使用示例:

makeProduct("46913872:2:Bust", 34); 

返回对象:

{
    attributes: {
        name: "Bust",
        productId: "46913872",
        quantityIterator: "2"
    },
    value: 34
}

answer中列出了按多个字段对对象进行排序的一般方法。

答案 4 :(得分:1)

这样的东西效果很好,你可以很容易地定义一个函数来包装它,并在给定比较属性的情况下对jQuery对象进行排序:

    var $jobj = jQuery( '.jcss' ); // your selector here
    var $jarr = [];

    $jobj.each( function () {
        $jarr.push( jQuery( this ) );
    } );

    $jarr.sort( function ( a, b ) {
        var attr = {}; // your comparison attribute here
        attr.a = parseInt( a.data( 'priority' ) || 0 );
        attr.b = parseInt( b.data( 'priority' ) || 0 );
        return attr.a < attr.b ? -1 : attr.a > attr.b ? 1 : 0;
    } );

    $jobj = jQuery( jQuery.map( $jarr, function ( obj, i ) {
        return obj[0];
    } ) );

    // whatever you need to do here
    $jobj.css( { 'text-decoration': 'blink' } );