从这个最初的问题,我将如何在多个字段应用排序?

使用这种稍作调整的结构,我将如何排序城市(上升)和价格(下降)?

var homes = [
    {"h_id":"3",
     "city":"Dallas",
     "state":"TX",
     "zip":"75201",
     "price":"162500"},
    {"h_id":"4",
     "city":"Bevery Hills",
     "state":"CA",
     "zip":"90210",
     "price":"319250"},
    {"h_id":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];

我喜欢的事实是,给出的答案提供了一个一般的方法。在我计划使用这段代码的地方,我将不得不对日期以及其他东西进行排序。“启动”对象的能力似乎很方便,如果不是有点麻烦的话。

我试图把这个答案构建成一个很好的通用示例,但我运气不太好。


当前回答

为了简化操作,可以使用这些辅助函数。

您可以根据需要对任意多个字段进行排序。对于每个排序字段,指定属性名,然后可选地指定-1作为排序方向,以降序排序而不是升序排序。

const data = [ {"h_id":"3","city":"Dallas","state":"TX","zip":"75201","price":"162500"}, {"h_id":"4","city":"Bevery Hills","state":"CA","zip":"90210","price":"319250"}, {"h_id":"6","city":"Dallas","state":"TX","zip":"75000","price":"556699"}, {"h_id":"5","city":"New York","state":"NY","zip":"00010","price":"962500"}, {"h_id":"7","city":"New York","state":"NY","zip":"00010","price":"800500"} ] const sortLexically = (p,d=1)=>(a,b)=>d * a[p].localeCompare(b[p]) const sortNumerically = (p,d=1)=>(a,b)=>d * (a[p]-b[p]) const sortBy = sorts=>(a,b)=>sorts.reduce((r,s)=>r||s(a,b),0) // sort first by city, then by price descending data.sort(sortBy([sortLexically('city'), sortNumerically('price', -1)])) console.log(data)

其他回答

这是一个通用的多维排序,允许在每个层次上进行反转和/或映射。

用Typescript编写。对于Javascript,请查看这个JSFiddle

的代码

type itemMap = (n: any) => any;

interface SortConfig<T> {
  key: keyof T;
  reverse?: boolean;
  map?: itemMap;
}

export function byObjectValues<T extends object>(keys: ((keyof T) | SortConfig<T>)[]): (a: T, b: T) => 0 | 1 | -1 {
  return function(a: T, b: T) {
    const firstKey: keyof T | SortConfig<T> = keys[0];
    const isSimple = typeof firstKey === 'string';
    const key: keyof T = isSimple ? (firstKey as keyof T) : (firstKey as SortConfig<T>).key;
    const reverse: boolean = isSimple ? false : !!(firstKey as SortConfig<T>).reverse;
    const map: itemMap | null = isSimple ? null : (firstKey as SortConfig<T>).map || null;

    const valA = map ? map(a[key]) : a[key];
    const valB = map ? map(b[key]) : b[key];
    if (valA === valB) {
      if (keys.length === 1) {
        return 0;
      }
      return byObjectValues<T>(keys.slice(1))(a, b);
    }
    if (reverse) {
      return valA > valB ? -1 : 1;
    }
    return valA > valB ? 1 : -1;
  };
}

用法示例

先按姓排序,再按名排序:

interface Person {
  firstName: string;
  lastName: string;
}

people.sort(byObjectValues<Person>(['lastName','firstName']));

按语言代码的名称排序,而不是按语言代码排序(见地图),然后按降序排序(见反向)。

interface Language {
  code: string;
  version: number;
}

// languageCodeToName(code) is defined elsewhere in code

languageCodes.sort(byObjectValues<Language>([
  {
    key: 'code',
    map(code:string) => languageCodeToName(code),
  },
  {
    key: 'version',
    reverse: true,
  }
]));
function sort(data, orderBy) {
        orderBy = Array.isArray(orderBy) ? orderBy : [orderBy];
        return data.sort((a, b) => {
            for (let i = 0, size = orderBy.length; i < size; i++) {
                const key = Object.keys(orderBy[i])[0],
                    o = orderBy[i][key],
                    valueA = a[key],
                    valueB = b[key];
                if (!(valueA || valueB)) {
                    console.error("the objects from the data passed does not have the key '" + key + "' passed on sort!");
                    return [];
                }
                if (+valueA === +valueA) {
                    return o.toLowerCase() === 'desc' ? valueB - valueA : valueA - valueB;
                } else {
                    if (valueA.localeCompare(valueB) > 0) {
                        return o.toLowerCase() === 'desc' ? -1 : 1;
                    } else if (valueA.localeCompare(valueB) < 0) {
                        return o.toLowerCase() === 'desc' ? 1 : -1;
                    }
                }
            }
        });
    }

使用:

sort(homes, [{city : 'asc'}, {price: 'desc'}])

var homes = [ {"h_id":"3", "city":"Dallas", "state":"TX", "zip":"75201", "price":"162500"}, {"h_id":"4", "city":"Bevery Hills", "state":"CA", "zip":"90210", "price":"319250"}, {"h_id":"6", "city":"Dallas", "state":"TX", "zip":"75000", "price":"556699"}, {"h_id":"5", "city":"New York", "state":"NY", "zip":"00010", "price":"962500"} ]; function sort(data, orderBy) { orderBy = Array.isArray(orderBy) ? orderBy : [orderBy]; return data.sort((a, b) => { for (let i = 0, size = orderBy.length; i < size; i++) { const key = Object.keys(orderBy[i])[0], o = orderBy[i][key], valueA = a[key], valueB = b[key]; if (!(valueA || valueB)) { console.error("the objects from the data passed does not have the key '" + key + "' passed on sort!"); return []; } if (+valueA === +valueA) { return o.toLowerCase() === 'desc' ? valueB - valueA : valueA - valueB; } else { if (valueA.localeCompare(valueB) > 0) { return o.toLowerCase() === 'desc' ? -1 : 1; } else if (valueA.localeCompare(valueB) < 0) { return o.toLowerCase() === 'desc' ? 1 : -1; } } } }); } console.log(sort(homes, [{city : 'asc'}, {price: 'desc'}]));

对两个日期字段和一个数字字段的排序示例:

var generic_date =  new Date(2070, 1, 1);
checkDate = function(date) {
  return Date.parse(date) ? new Date(date): generic_date;
}

function sortData() {  
  data.sort(function(a,b){
    var deltaEnd = checkDate(b.end) - checkDate(a.end);
    if(deltaEnd) return deltaEnd;

    var deltaRank = a.rank - b.rank;
    if (deltaRank) return deltaRank;

    var deltaStart = checkDate(b.start) - checkDate(a.start);
    if(deltaStart) return deltaStart;

    return 0;
  });
}

http://jsfiddle.net/hcWgf/57/

只是另一种选择。考虑使用以下效用函数:

/** Performs comparing of two items by specified properties
 * @param  {Array} props for sorting ['name'], ['value', 'city'], ['-date']
 * to set descending order on object property just add '-' at the begining of property
 */
export const compareBy = (...props) => (a, b) => {
  for (let i = 0; i < props.length; i++) {
    const ascValue = props[i].startsWith('-') ? -1 : 1;
    const prop = props[i].startsWith('-') ? props[i].substr(1) : props[i];
    if (a[prop] !== b[prop]) {
      return a[prop] > b[prop] ? ascValue : -ascValue;
    }
  }
  return 0;
};

用法示例(在您的情况下):

homes.sort(compareBy('city', '-price'));

值得注意的是,这个函数可以更一般化,以便能够使用嵌套属性,如'address '。City '或'style.size。宽度”等。

您可以使用lodash或derby函数lodash

它有两个参数字段数组和方向数组('asc','desc')

  var homes = [
    {"h_id":"3",
     "city":"Dallas",
     "state":"TX",
     "zip":"75201",
     "price":"162500"},
    {"h_id":"4",
     "city":"Bevery Hills",
     "state":"CA",
     "zip":"90210",
     "price":"319250"},
    {"h_id":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];

var sorted =. data._.orderBy(data, ['city', 'price'], ['asc','desc'])