返回列表

数组 排序 多属性 多字段 第一排序字段 第二排序字段 sortBy

默认分类 2017/09/21 01:43

数组排序本来很简单,大多数场景一个sort方法足以搞定,多属性排序在设计参数格式时遇到了点小麻烦,由于对象的属性键值对不支持顺序读取(Map 是支持有序键值对的), 最终将参数设计成 [['a', 'asc'], ['b', 'asc']] 这样的方式了,不过也支持 sortBy([], 'a', 'desc') 。

实现代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <script>
  'use strict'
  // sortBy([], 'a', 'desc') => sortBy([], [['a', 'desc']])
  // sortBy([], ['a', ['b']]) => sortBy([], [['a', 'asc'], ['b', 'asc']])
  function sortBy(list, field, order) { // order: 1 asc, -1 desc, 0 ''
    if (!list || !list.sort || !list.length) return list
    var sort = []
    if (typeof field === 'string') {
      sort.push([field, order === undefined ? 'asc' : String(order)])
    } else if (Object.prototype.toString.call(field) === '[object Array]') {
      sort = field
    }

    for (var i = sort.length - 1; i > -1; i--) {
      if (typeof sort[i] === 'string') {
        sort[i] = [sort[i], 'asc']
      } else if (Object.prototype.toString.call(sort[i]) === '[object Array]') {
        if (typeof sort[i][0] !== 'string') sort[i][0] = String(sort[i][0])
        if (String(sort[i][1]) === '-1' || String(sort[i][1]).toLowerCase() === 'desc') {
          sort[i][1] = 'desc'
        } else if (String(sort[i][1]) === '0') {
          sort[i][1] = '0'
        } else sort[i][1] = 'asc'
      }
    }
    console.log(sort)
    list.sort(function(a, b) {
      var m, n, result = 0
      for (var i = 0, len = sort.length; i < len; i++) {
        if (sort[i][1] === '0') continue;

        if (Object.prototype.toString.call(a[sort[i][0]]) === '[object Number]' 
          && Object.prototype.toString.call(b[sort[i][0]]) === '[object Number]') {
          m = a[sort[i][0]]
          n = b[sort[i][0]]
        } else {
          m = String(a[sort[i][0]]).toLowerCase()
          n = String(b[sort[i][0]]).toLowerCase()
        }
        result = (m > n ? 1 : m < n ? -1 : 0) * (sort[i][1] === 'desc' ? -1 : 1)

        if (result) break
      }
      return result
    })
    return list
  }

  // sortBy([{a:1,b:2},{a:1,b:3},{a:2,b:2}], [['a',1], ['b', -1]])


  // ['a', 'desc', 'b', '', 'c']
  // [{key: 'a', order: -1},{key: 'b', order: 1}]
  // [['a', -1],['b', 1], 'c', ['d']]
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a', -1)) === '[{"a":3,"b":2},{"a":2,"b":2},{"a":1,"b":3}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a', '-1')) === '[{"a":3,"b":2},{"a":2,"b":2},{"a":1,"b":3}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a', 'desc')) === '[{"a":3,"b":2},{"a":2,"b":2},{"a":1,"b":3}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a', 'dEsc')) === '[{"a":3,"b":2},{"a":2,"b":2},{"a":1,"b":3}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a', 0)) === '[{"a":3,"b":2},{"a":1,"b":3},{"a":2,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a', '0')) === '[{"a":3,"b":2},{"a":1,"b":3},{"a":2,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a', 1)) === '[{"a":1,"b":3},{"a":2,"b":2},{"a":3,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a', '1')) === '[{"a":1,"b":3},{"a":2,"b":2},{"a":3,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a', 'asc')) === '[{"a":1,"b":3},{"a":2,"b":2},{"a":3,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a', 'aSc')) === '[{"a":1,"b":3},{"a":2,"b":2},{"a":3,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], 'a')) === '[{"a":1,"b":3},{"a":2,"b":2},{"a":3,"b":2}]')

  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], ['a'])) === '[{"a":1,"b":3},{"a":2,"b":2},{"a":3,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], [['a', -1]])) === '[{"a":3,"b":2},{"a":2,"b":2},{"a":1,"b":3}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], [['a', '-1']])) === '[{"a":3,"b":2},{"a":2,"b":2},{"a":1,"b":3}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], [['a', 'desc']])) === '[{"a":3,"b":2},{"a":2,"b":2},{"a":1,"b":3}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], [['a', 'dEsc']])) === '[{"a":3,"b":2},{"a":2,"b":2},{"a":1,"b":3}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], [['a', 1]])) === '[{"a":1,"b":3},{"a":2,"b":2},{"a":3,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], [['a', '1']])) === '[{"a":1,"b":3},{"a":2,"b":2},{"a":3,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], [['a', 'asc']])) === '[{"a":1,"b":3},{"a":2,"b":2},{"a":3,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], [['a', 'aSc']])) === '[{"a":1,"b":3},{"a":2,"b":2},{"a":3,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], [['a', 0]])) === '[{"a":3,"b":2},{"a":1,"b":3},{"a":2,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:1,b:3},{a:2,b:2}], [['a', '0']])) === '[{"a":3,"b":2},{"a":1,"b":3},{"a":2,"b":2}]')

  console.log(JSON.stringify(sortBy([{a:3,b:2},{a:3,b:3},{a:2,b:2}], ['a', ['b', -1]])) === '[{"a":2,"b":2},{"a":3,"b":3},{"a":3,"b":2}]')
  console.log(JSON.stringify(sortBy([{a:1,b:2},{a:1,b:3},{a:2,b:2}], [['a', -1], ['b', -1]])) === '[{"a":2,"b":2},{"a":1,"b":3},{"a":1,"b":2}]')

  </script>
</body>

</html>