JavaScript骨干集合在多个字段上排序

Aks*_*hay 1 javascript sorting jquery backbone.js underscore.js

我有像这样的数据

-------------------------
id | name | parentId
-------------------------
1  | a    |
2  | z    |
3  | b    |
4  | z1   | 2
5  | y2   | 1
6  | y1   | 1
7  | y3   | 1
-------------------------
Run Code Online (Sandbox Code Playgroud)

在骨干集合中.

我想对字段名称进行排序,但是子对象应该放在父对象下面(基于parentId),

-------------------------
id | name | parentId
-------------------------
1  | a    |
6  | y1   | 1
5  | y2   | 1
7  | y3   | 1
3  | b    |
2  | z    |
4  | z1   | 2
-------------------------
Run Code Online (Sandbox Code Playgroud)

这里y1,y2和y3是向上的,因为它们是a(id 1)的子节点.

我正在使用骨干收集比较器.(但只有javasript的比较器会做 - 我将转换为骨干比较器).

thi*_*uts 5

var comparator = function(a, b) {
    var aName = a.get('name'), 
        bName = b.get('name'),
        aParentId = a.get('parentId'),
        bParentId = b.get('parentId');

    if(!aParentId || !bParentId || aParentId == bParentId) {
         // In these 3 cases, name has precedence

        if(aName < bName) {
            return -1;
        } 
        else if(aName > bName) {
            return 1;
        }
        else {
            return 0;
        }

    } else if(aParentId < bParentId) {
        return -1;
    } else /* aParentId > bParentId */ {
        return 1;
    }
};
Run Code Online (Sandbox Code Playgroud)

编辑:更正.必须考虑两个排序级别,请记住,任何缺少的parentId都等于parentIds.

您还可以将其实现为字段/定制的比较器列表,这些比较器一个接一个地执行,其中下一个比较器在当前发现相等时被委派给它.

var loopedComparator = function(a, b) {
  var fields = [
    {
      name: 'parentId', 
      comparator: function(a, b) {
        return (!a || !b || a == b) ? 0 : (a < b) ? -1 : 1;
      }
    },
    {
      name: 'name',
      comparator: function(a, b) {
        return (a == b) ? 0 : (a < b) ? -1 : 1;
      }
    }
  ];

  var i, result = 0;
  for(i in fields) {
    var field = fields[i];
    result = field.comparator(a.get(field.name), b.get(field.name));
    if(result !== 0) {
      return result; // On inequality we return right away
    }
    // Else we continue, delegating the comparison to the next field / comparator
  }

  // When the loop is done, or if fields was defined empty, we return the last equality
  return result;

};
Run Code Online (Sandbox Code Playgroud)

当然,使用此方案,您可以根据需要添加任意数量的列,并为每个列定义自定义比较器.