Как отсортировать массив с coffeescript?
с массивом, подобным этому:
users = [
{ id: 1, fname: 'Fred', lname: 'Flinstone', state: 'CA' },
{ id: 2, fname: 'George', lname: 'Winston', state: 'FL' },
{ id: 3, fname: 'Luke', lname: 'Skywalker', state: 'CA' }
]
и вы хотите сортировать по фамилии с coffeescript, вы можете сделать это:
users.sort (a,b) ->
return if a.lname.toUpperCase() >= b.lname.toUpperCase() then 1 else -1
Я попытался использовать такую функцию:
sortBy = (field, reverse, primer) ->
key = (x) ->
return if primer? then primer x[field] else x[field]
return (a,b) ->
A = key a
B = key b
return (A < B ? -1 : (A > B ? 1 : 0)) * [1,-1][+!!reverse]
который был вызван следующим образом:
users.sort sortBy "lname", false, (a) ->
return a.toUpperCase()
но это не правильно сортировало массив.
Есть ли способ сортировки более чем на 1 поле, т.е. сортировка сначала по состоянию, а затем по имени? Я надеялся улучшить функцию "sortBy" выше и добавить способность сортировать по меньшей мере по 2 полям.
Ответы
Ответ 1
Там более простой способ. Просто повторите использование своей обобщенной функции сортировки и объедините их с помощью ||
:
sortBy = (key, a, b, r) ->
r = if r then 1 else -1
return -1*r if a[key] > b[key]
return +1*r if a[key] < b[key]
return 0
users.sort (a,b) ->
sortBy('id', a, b, true) or
sortBy('lname', a, b) or
sortBy('fname', a, b)
Функции дешевы. Затем вы можете построить абстракцию для этого:
sortByMultiple = (a, b, keys) ->
return r if (r = sortBy key, a, b) for key in keys
return 0
users.sort (a,b) -> sortByMultiple a, b, ['id', 'lname', 'fname']
Но тогда вы теряете возможность устанавливать порядок или другие параметры для каждого из них.
Ответ 2
В качестве альтернативы вам может потребоваться использовать Underscore sortBy, t выполнить его самостоятельно:
_(users).sortBy (u) -> [u.state, u.lname.toUpperCase()]
Ответ 3
Это то, что, по моему мнению, было бы реализовано по умолчанию при использовании lodash, но это не так.
Итак, вот мы!
sortByLowercase: (collection, key) ->
collection.sort (a, b) ->
[av, bv] = [a[key], b[key]]
[av, bv] = [av.toLowerCase(), bv.toLowerCase()]
if av >= bv then 1 else if av <= bv then -1 else 0
sortByLowercase(users,'lname')
На основе более общего примера я нашел здесь