Nice programing

녹아웃에서 관찰 가능한 배열 정렬

nicepro 2020. 11. 21. 09:17
반응형

녹아웃에서 관찰 가능한 배열 정렬


Knockout of person objects에 관찰 가능한 배열이 있습니다. 성을 기준으로 사람 목록을 정렬 할 수 있기를 원했습니다. 문제는 목록에 여러 개의 중복 성이 있다는 것입니다. 결과적으로 성이 둘 이상인 경우 이름이 발견 된대로 나타납니다. 성을 기준으로 배열을 정렬하고 성이 둘 이상인 경우 이름으로도 정렬하고 싶습니다. 사용자가 성을 입력하기 위해 텍스트 입력을 사용하고 있습니다. 결과는 모든 일치 항목을 표시하는 템플릿에 바인딩됩니다.

<input data-bind="value: filter, valueUpdate: 'afterkeydown'">

그리고 다음은 내 녹아웃 배열 필터 코드입니다.

function Item(firstname, lastname) {
     this.firstname = ko.observable(firstname);
     this.lastname = ko.observable(lastname);
}

var playersViewModel = {
     items: ko.observableArray([]),
     filter: ko.observable("")
};
var players;

$(function() {
    playersViewModel.filteredItems = ko.computed(function() {
         var filter = this.filter().toLowerCase();
         if (!filter) {
              return this.items();
         } else {
              return ko.utils.arrayFilter(this.items(), function(item) {
                    return ko.utils.stringStartsWith(item.lastname().toLowerCase(), filter);
              });
         }
    }, playersViewModel);

    $.getJSON('./players.json', function(data) {
        players = data.players;
        playersViewModel.players = ko.observableArray(players);
        ko.applyBindings(playersViewModel);    
        var mappedData = ko.utils.arrayMap(players, function(item) {
             return new Item(item.firstname,item.lastname);
        });
        playersViewModel.items(mappedData);
    });    
});

성 필터링의 경우 잘 작동하지만 성이 중복되면 이름 정렬에 추가하는 방법을 찾을 수 없습니다. 예를 들어, 성을 기준으로 정렬하면 배열에서 다음을 얻습니다.

Joe Bailey
Jack Brown
Adam Brown
Bob Brown
Jim Byrd

중복 된 성이 이름도 정렬되도록하고 싶습니다.

Joe Bailey
Adam Brown
Bob Brown
Jack Brown
Jim Byrd

KnockoutJS 관찰 가능 배열은 정렬 기능을 제공하므로 데이터의 자연스러운 순서에 관계없이 UI에서 데이터 바인딩 된 배열을 비교적 쉽게 정렬 할 수 있습니다.

data-bind="foreach: items.sort(function (l, r) { return l.lastName() > r.lastName() ? 1 : -1 })"

바인딩하기 전에 정렬 (또는 정렬로 인한 리 바인딩)하는 경우 소스 데이터를 사전 정렬 / 재정렬 할 필요가 없습니다.

즉, 당신이 요청하는 것은 두 개의 데이터, 성, 이름으로 정렬하는 것입니다.

"l.lastName ()> r.lastName ()? 1 : -1"대신 다음을 고려하십시오.

l.lastName() === r.lastName() 
    ? l.firstName() > r.firstName() ? 1 : -1
    : l.lastName() > r.lastName() ? 1 : -1

이것은 더 효율적일 수 있습니다. 기본적으로 세 가지 조건이 있습니다.

  1. 성이 같은가요?
  2. 그렇다면 이름을 비교하고 결과를 반환하십시오.
  3. 그렇지 않으면 성을 비교하고 결과를 반환합니다.

귀하의 코드를 스캔 한 결과 그러한 정렬 기능이 없습니다.

This is similar to Michael Best's answer, however, I've attempted to clarify WHERE to handle sorting (in your binding, first example) and HOW to achieve the sort you're looking for (multiple datum.)

data-bind="foreach: items().sort(function (l, r) { return (l.lastName() == r.lastName()) ? (l.firstName() > r.firstName() ? 1 : -1) : (l.lastName() > r.lastName() ? 1 : -1) })"

Naturally, this can get unwieldy as you introduce more sort vectors, such as reversals or additional datum, and so you should implement a filter function that performs the above evaluation for you:

data-bind="foreach: items().sort(my.utils.compareItems)"

If you make sure your players.json returns the names sorted, you'll be fine. If it's loading them from a database, you need to add the first name field to your ORDER BY clause.

If you want to do the sorting in Javascript, you could do it right after you load it from the service:

players.sort(function(player1, player2) {
    return player1.lastname.localeCompare(player2.lastname) ||
        player1.firstname.localeCompare(player2.firstname);
});

I had some issues trying to sort a observable array, I was not seeing any results in my code.

You need to sort the results you receive via ajax/getJSON request first, before you return the new items into your array.

This way the results are sorted before they are added into your observable array as new items. No need to sort them at the bindings then.

See the example below.

players(ko.utils.arrayMap(result, function (item) {
                    result.sort(function (l, r) {
                        return l.name == r.name ? 0 : (l.name < r.name ? -1 : 1);
                    });
                return new Player(item);
            }));
  1. get data using AJAX / getJSON
  2. Sort the result of that request into your array of choice

You have to use Two sort to do this .In first sorting , sort according to persons last name And In 2nd Sorting first Search according to last name if more than two persons have same last name than sort these according to their first name at their location , using some Standard sorting Algorithm ....

참고URL : https://stackoverflow.com/questions/12718699/sorting-an-observable-array-in-knockout

반응형