Javascript 自然排序、对象数组、多列、反转等

Javascript 自然排序、对象数组、多列、反转等,javascript,sorting,underscore.js,lodash,ramda.js,Javascript,Sorting,Underscore.js,Lodash,Ramda.js,我迫切需要实现客户端排序,通过我们的tastypieapi模拟排序,它可以获取多个字段并返回排序数据。例如,如果我有如下数据: arr = [ { name: 'Foo LLC', budget: 3500, number_of_reqs: 1040 }, { name: '22nd Amendment', budget: 1500, number_of_reqs: 2000 }, { name: 'STS 10', budget: 50000,

我迫切需要实现客户端排序,通过我们的tastypieapi模拟排序,它可以获取多个字段并返回排序数据。例如,如果我有如下数据:

arr = [ 
  { name: 'Foo LLC',        budget: 3500,  number_of_reqs: 1040 }, 
  { name: '22nd Amendment', budget: 1500,  number_of_reqs: 2000 },
  { name: 'STS 10',         budget: 50000, number_of_reqs: 500  },
  ...
  etc.
]
和给定的要排序的列,例如:
['name','-number\u of_reqs']
它应该按
名称
(升序)和
数量
(降序)排序。我想不起来了, 首先,它必须是“自然排序”,如果我们谈论的是对单个列进行排序,那么它应该很容易获得,但我需要能够对多个列进行排序

另外,我也不清楚为什么在使用lodash的
\uuu.sortBy
时会得到不同的结果(从api的工作方式来看)?
\uuu.sortBy
不是“自然的”还是我们的api坏了

我也在寻找一个优雅的解决方案。最近刚开始使用,真是太棒了。我打赌这会更容易建立排序我需要使用它?我已经试过了,但还是做不好。帮个小忙

upd:

我发现它并与Ramda一起使用,如下所示:

fn = R.compose(R.sort(naturalSort), R.pluck("name"))
fn(arr)
var on = R.curry(function(map, cmp) { return R.useWith(cmp, map, map); return R.useWith(cmp, [map, map]); // since Ramda >0.18 });
var props = ["-budget", "name"];
var comparator = Ru.compareProps(props);
var sortedList = R.sort(comparator, arr);

似乎适用于平面数组,但我仍然需要找到一种方法将其应用于数组中的多个字段

使用javascript本机排序:


Array.prototype.multisort=函数(列){
var arr=此;
arr.sort(函数(a,b){
返回比较(a、b、0);
});
函数比较(a、b、colindex){
if(colindex>=columns.length)返回0;
var columnname=列[colindex];
变量a_field1=a[columnname];
var b_field1=b[columnname];
var asc=(共索引%2==0);
如果(a_字段1b_字段1)返回asc?1:-1;
否则返回比较(a、b、colindex+1);
}
}
var arr=[{name:'Foo LLC',预算:3500,需求数量:1040},
{名称:'22修正案',预算:1500,需求数量:2000},
{名称:'STS 10',预算:50000,需求数量:5000},
{名称:'STS 10',预算:50000,需求数量:500}];
arr.multisort(['name','number'u of_reqs');
if(window.console)window.console.log(arr)我认为这是可行的

var-arr=[
{名称:'Foo LLC',预算:3500,需求数量:1040},
{名称:'22修正案',预算:1500,需求数量:2000},
{名称:'STS 10',预算:50000,需求数量:5000},
{名称:'STS 10',预算:50000,需求数量:500}
];
变量列=[“名称”,“需求数量];
变量组数=/(?\d*\。?\d+)/g;
var naturalSort=函数(a、b、columnname){
变量a_field1=a[columnname],
b_field1=b[columnname],
aa=字符串(a_字段1)。拆分(数量_组),
bb=字符串(b_字段1)。拆分(组数),
最小=数学最小值(aa.长度,bb.长度);
对于(变量i=0;iy),则返回1;
}
返回0;
};
arr.sort(函数(a,b){
var结果;
对于(var i=0;i
看起来很有效

真的吗?我希望返回已排序的名称数组,而不是按名称属性对对象数组进行排序

不幸的是,使用
sortBy
无法提供自定义的比较函数(自然排序所需),将多个列组合在一个值中进行一致比较可能是可行的,但很麻烦

我仍然不知道如何对多个字段执行此操作

函数式编程在这里可以做很多事情,不幸的是Ramda并没有真正为比较器配备有用的函数(除了)。我们还需要三名助手:

  • on
    (如),它采用
    a->b
    转换和
    b->b->Number
    比较器函数在两个
    a
    s上生成比较器。我们可以用Ramda创建它,如下所示:

    fn = R.compose(R.sort(naturalSort), R.pluck("name"))
    fn(arr)
    
    var on = R.curry(function(map, cmp) { return R.useWith(cmp, map, map); return R.useWith(cmp, [map, map]); // since Ramda >0.18 });
    var props = ["-budget", "name"];
    var comparator = Ru.compareProps(props);
    var sortedList = R.sort(comparator, arr);
    
  • 求反
    -一种对比较进行求反的函数:

    function negate(cmp) { return R.compose(R.multiply(-1), cmp); }
    Bergi的答案很有用,也很有趣,但它改变了您所请求的API。下面是一个创建您正在寻找的API的示例:

    var multisort = (function() {
        var propLt = R.curry(function(name, a, b) {
            return a[name] < b[name];
        });
        return function(keys, objs) {
            if (arguments.length === 0) {throw new TypeError('cannot sort on nothing');}
            var fns = R.map(function(key) {
                return key.charAt(0) === "-" ? 
                    R.pipe(R.comparator(propLt(R.substringFrom(1, key))), R.multiply(-1)) :
                    R.comparator(propLt(key));
            }, keys);
            var sorter = function(a, b) {
                return R.reduce(function(acc, fn) {return acc || fn(a, b);}, 0, fns);
            }
            return arguments.length === 1 ? R.sort(sorter) : R.sort(sorter, objs);
        };
    }());
    
    multisort(['name', '-number_of_reqs'], arr); //=> sorted clone
    
    var multisort=(函数(){
    var propLt=R.curry(函数名,a,b){
    返回a[name]分类克隆
    

    它是手动curry而不是调用
    R.curry
    ,因为创建单独的排序函数需要相当多的工作,如果使用同一组键对多个列表进行排序,则可以重用这些函数。如果这不是一个问题,这可以简化一点。

    如果您愿意为您的项目添加另一个依赖项,则会提供一个compareProps函数,它完全满足原始问题的要求

    因此,根据您最初的示例,按照预算和名称进行降序排序,您可以执行以下操作:

    fn = R.compose(R.sort(naturalSort), R.pluck("name"))
    fn(arr)
    
    var on = R.curry(function(map, cmp) { return R.useWith(cmp, map, map); return R.useWith(cmp, [map, map]); // since Ramda >0.18 });
    var props = ["-budget", "name"];
    var comparator = Ru.compareProps(props);
    var sortedList = R.sort(comparator, arr);
    

    升序,降序呢?升序返回结果,-降序返回结果。您还可以在compare方法中使用一个标志并否定降序的输出。这是javascript中最自然的输出。B