2012-01-19 2 views
40
this.col = Backbone.Collection.extend({ 
    model: M, 
    comparator: function(item) { 
     return item.get("level"); 
    } 
    }); 

위 코드는 레벨별로 항목을 정렬합니다. 나는 레벨별로, 그리고 제목별로 정렬하고 싶다. 내가 할 수 있을까? 감사.Backbone.js 컬렉션 비교 자 여러 필드별로 정렬 하시겠습니까?

+3

2012 년 초부터 정렬 스타일 비교기가 지원됩니다. 2 개의 인수를 허용하고 -1, 0 또는 1을 반환합니다. https : // github.com/documentcloud/backbone/commit/6b3ff7b0359510917d9ead8c8e16a7457eef05ef – geon

답변

72
amchang87의 대답은 확실히 작동 @

하지만 단순히 정렬 필드의 배열 반환 가공 한 발견 다른 : 아직

this.col = Backbone.Collection.extend({ 
    model: M, 
    comparator: function(item) { 
     return [item.get("level"), item.get("title")] 
    } 
}); 

내가 여러 브라우저에서이 테스트를하지 않은 나는 그것이 JS에 의존 생각하는 '배열의 내용을 기준으로 정렬 순서로 동작합니다. 그것은 확실히 WebKit에서 작동합니다.

+5

2012 년 초부터 정렬 스타일 비교기가 지원됩니다. 2 개의 인수를 허용하고 -1, 0 또는 1을 반환합니다. https://github.com/documentcloud/backbone/commit/6b3ff7b0359510917d9ead8c8e16a7457eef05ef – geon

+2

이렇게 간단합니다. 기술입니다. 다음은 CoffeeScript의 예제입니다. https://gist.github.com/jhabdas/9822535 –

+5

(적어도 Webkit에서는) 두 필드가 문자열로 비교됩니다. 숫자 정렬을하려고한다면 1, 10, 2, 20, 200 등으로 끝날 것입니다. – RobW

1

주요한 점은 백본이 한 항목의 단일 상대 값으로 정렬한다는 것입니다. 그래서 그것은 하나의 컬렉션에서 두 번 정렬하는 것이 직접 가능하지 않지만 이것을 시도 할 것입니다.

this.col = Backbone.Collection.extend({ 
    model: M, 
    comparator: function(item) { 
     // make sure this returns a string! 
     return item.get("level") + item.get("title"); 
    } 
}); 

는 이것이 할 것입니다 것은 "1Cool", "1title", "2newTitle"등의 문자열을 반환은 ... 자바 스크립트는 각 문자 이후 먼저 숫자 문자로 문자열을 정렬해야한다. 하지만 이것은 레벨의 숫자가 같은 한만 작동합니다. IE "001title"vs "200title" 그러나 주된 아이디어는 하나의 기준에 따라 서로 비교할 수있는 두 개의 비교 가능한 객체, 즉 숫자 또는 문자열을 생성해야한다는 것입니다.

다른 해결책은 레벨을 "groupby"하기 위해 밑줄을 사용하고 "sortby"를 사용하여 수동으로 각 레벨 그룹을 정렬 한 다음 수동으로 새로 생성 된 배열로 기본 모음을 교체하는 것입니다. 컬렉션이 "변경"될 때마다이 작업을 수행하는 기능을 설정할 수 있습니다.

+0

내 데이터 모델링을 망칠 수있는 'groupby'방법을 이해한다면 그렇지 않습니까? 첫 번째 솔루션은 다소 훌륭하지만, 덕분입니다. – Harry

+0

이것이 최선의 방법인지 확신하지 못합니다. 예를 들어, model1-> level : 1, title : "1-thing"의 두 모델이 있다면; model2 -> level : 10, title : "-thing"이면 model1, model2로 정렬 될 것이라고 기대할 수 있습니다. 그러나 비교 자에 의해 문자열 "11-thing"과 "10-thing"을 비교하게됩니다. –

+0

이것은 배열로 정렬하려고하는 것과 똑같은 기능을하며, 단일 인수 비교 함수에서'[1, 'x']'를 반환하면 비교하는 대신 문자열''1, x "'로 정렬됩니다 요소들. –

7

여러 필드를 오름차순으로 정렬 할 때 문자열 연결이 잘 작동하지만 1) 필자가 필드 당 asc/desc를 지원해야하고 2) 특정 필드가 숫자 필드 였기 때문에 문자열 연결이 정상적으로 작동합니다. 오름차순이면 2를 따라 올 것입니다.) 그래서 아래는 필자가 사용하고 비교할 필요가있는 비교 함수입니다. 백본 컬렉션에는 필드 이름과 정렬 순서 방향이있는 JSON 객체의 배열 인 'sortConfig'가 할당 된 변수가 있다고 가정합니다. 예를 들어, 모음 'sortConfig'으로 지정된 상기 JSON 개체

{ 
    "sort" : [ 
     { 
      "field": "strField", 
      "order": "asc" 
     }, 
     { 
      "field": "numField", 
      "order": "desc" 
     }, 
     ... 
    ] 
} 

는 아래 함수는 등의 경우, 내림차순 numField하여 다음 정렬 제 오름차순 strField 의해 백본 정렬 것 정렬 순서가 지정되면 기본적으로 오름차순으로 정렬됩니다. 당신이 하강 일부 오름차순으로 정렬해야하는 경우 배열을 반환

multiFieldComparator: function(one, another) { 
    // 'this' here is Backbone Collection 
    if (this.sortConfig) { 
     for (var i = 0; i < this.sortConfig.length; i++) { 
      if (one.get(this.sortConfig[i].field) > another.get(this.sortConfig[i].field)) { 
       return ("desc" != this.sortConfig[i].order) ? 1 : -1; 
      } else if (one.get(this.sortConfig[i].field) == another.get(this.sortConfig[i].field)) { 
       // do nothing but let the loop move further for next layer comparison 
      } else { 
       return ("desc" != this.sortConfig[i].order) ? -1 : 1; 
      } 
     } 
    } 
    // if we exited out of loop without prematurely returning, the 2 items being 
    // compared are identical in terms of sortConfig, so return 0 
    // Or, if it didn't get into the if block due to no 'sortConfig', return 0 
    // and let the original order not change. 
    return 0; 
} 
2

내가 백본 비교기에 다시 관련 비교 정수를 반환하는 데 사용할 수있는 기능의 작은 세트를 생성 ... 일치하지 않습니다 기능 :

backbone-collection-multisort

0

hyong 응답에서 "영감".

또한 데이터를 비교하기 전에 데이터를 변경할 수 있습니다. valueTransforms는 개체이며, 해당 개체에 함수가있는 경우 사용됩니다.

/* 
    * @param {Object} sortOrders ie: 
    * { 
    *  "description": "asc", 
    *  "duedate": "desc", 
    * } 
    * @param {Object} valueTransforms 
    */ 
    setMultiFieldComparator: function(sortOrders, valueTransforms) { 
     var newSortOrders = {}, added = 0; 
     _.each(sortOrders, function(sortOrder, sortField) { 
      if (["asc", "desc"].indexOf(sortOrder) !== -1) { 
       newSortOrders[sortField] = sortOrder; 
       added += 1; 
      } 
     }); 
     if (added) { 
      this.comparator = this._multiFieldComparator 
       .bind(this, newSortOrders, valueTransforms || this.model.prototype.valueTransforms || {}); 
     } else { 
      this.comparator = null; 
     } 
    }, 

    _multiFieldComparator: function(sortOrders, valueTransforms, one, another) { 
     var retVal = 0; 
     if (sortOrders) { 
      _.every(sortOrders, function(sortOrder, sortField) { 
       var oneValue = one.get(sortField), 
        anotherValue = another.get(sortField); 
       if (valueTransforms[sortField] instanceof Function) { 
        oneValue = valueTransforms[sortField](oneValue); 
        anotherValue = valueTransforms[sortField](anotherValue); 
       } 
       if (oneValue > anotherValue) { 
        retVal = ("desc" !== sortOrder) ? 1 : -1; 
       } else if (oneValue < anotherValue) { 
        retVal = ("desc" !== sortOrder) ? -1 : 1; 
       } else { 
        //continue 
        return true; 
       } 
      }); 
     } 
     return retVal; 
    }, 
관련 문제