在淘汰赛中对可观察数组进行排序 [英] Sorting an Observable Array in Knockout

查看:87
本文介绍了在淘汰赛中对可观察数组进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在淘汰对象对象中有一个可观察的数组.我希望能够根据姓氏对人员列表进行排序.问题在于列表中有许多重复的姓氏.结果是,当一个以上的姓氏时,名字的名称会随着被找到而出现.我希望能够按姓氏对数组进行排序,并且当有多个姓氏时,也可以按姓氏对数组进行排序.我正在使用文本输入,供用户开始输入姓氏.结果绑定到显示所有匹配项的模板.

I have an observable array in Knockout of person objects. I wanted to be able to sort the list of persons based on the last name. The problem is the list has a number of duplicate last names. The result is that when there are more than one last name, the first names appear as they were found. I'd like to be able to sort the array by last name and when there are more than one last name, have it also sort by first name. I'm using a text input for the user to start typing in the last name. The results are bound to a template that displays all the matches.

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

这是我的淘汰赛数组过滤器代码:

And here is my Knockout array filter code:

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);
    });    
});

对于姓氏过滤,这可以很好地工作,但是当姓氏重复时,我无法找到一种方法来添加对名字的排序.例如,在我的数组中,按姓氏排序时,我得到:

For last name filtering this works fine, but I'm unable to find a way to add in sorting first name when there are duplicate last names. For example, in my array when sorted by last name I'm getting:

Joe Bailey
Jack Brown
Adam Brown
Bob Brown
Jim Byrd

我希望重复的姓氏也能对其名字进行排序:

I'd like the duplicate last names to have their first names sorted as well:

Joe Bailey
Adam Brown
Bob Brown
Jack Brown
Jim Byrd

推荐答案

KnockoutJS可观察数组提供了排序功能,这使得在UI中对数据绑定数组进行排序相对容易(无论数据的自然顺序如何).

KnockoutJS observable arrays offer a sort function, this makes it relatively easy to sort a databound array in your UI (regardless of the natural order of the data.)

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

您不必对源数据进行预排序/重新排序,如果在绑定之前进行排序(或由于排序而重新绑定),那么您做错了.

You should not have to pre-sort/re-sort your source data, if you're sorting before binding (or rebinding due to a sort) then you're doing it wrong.

也就是说,您要问的是按两个数据排序,姓,然后名字.

That said, what you're asking is to sort by two datum, last name, then first name.

考虑以下内容,而不是"l.lastName()> r.lastName()?1:-1":

Instead of "l.lastName() > r.lastName() ? 1 : -1" consider the following:

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

我敢肯定,这可能会更有效率.基本上,您有三个条件在玩:

This could be more efficient, I'm sure. Basically you have three conditionals at play:

  1. 姓氏是否相等?
  2. 如果是这样,比较名字并返回结果.
  3. 否则,比较姓氏并返回结果.

我已经扫描了您的代码,但没有合适的排序功能.

I've scanned your code and I see no such sort function in place.

这与Michael Best的答案类似,但是,我试图阐明WHERE来处理排序(在您的绑定中,第一个示例),以及如何实现所需的排序(多个数据).

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)"

这篇关于在淘汰赛中对可观察数组进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆