iLe*_*ing 2 javascript sorting underscore.js lodash ramda.js
我迫切需要实现客户端排序,它通过我们的tastypie api模拟排序,它可以占用多个字段并返回排序数据.所以,例如,如果我有以下数据:
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.
]
Run Code Online (Sandbox Code Playgroud)
给定列进行排序,例如:['name', '-number_of_reqs']它应该按name(升序)和number_of_reqs(降序)排序.我无法理解这一点,首先它必须是"自然排序",如果我们谈论排序单个列,它应该很容易获得,但我需要能够排序多.
此外,我不确定为什么我在使用lodash时会得到不同的结果(从api的方式来看)_.sortBy?是_.sortBy不是"自然"还是我们的api坏了?
我也在寻找一个优雅的解决方案.刚刚开始使用Ramdajs,它真是太棒了.我敢打赌,建立我需要使用的排序会更容易吗?我试过了,仍然无法做对.帮助不大?
UPD:
我找到了这个并将其与Ramda一起使用,如下所示:
fn = R.compose(R.sort(naturalSort), R.pluck("name"))
fn(arr)
Run Code Online (Sandbox Code Playgroud)
似乎适用于平面数组,但我仍然需要找到一种方法将它应用于我的数组中的多个字段
Run Code Online (Sandbox Code Playgroud)fn = R.compose(R.sort(naturalSort), R.pluck("name"))好像在起作用
真?我希望返回一个已排序的名称数组,而不是按名称属性对对象数组进行排序.
sortBy不幸的是,我们不允许使用自定义比较函数(自然排序所需),并且在单个值中组合多个列可能是一致的,但是很麻烦.
我仍然不知道如何为多个领域做这件事
功能编程在这里可以做很多事情,不幸的是Ramda并没有为比较器配备有用的功能(除了R.comparator).我们需要三个额外的助手:
on(就像来自Haskell的那个),它采用a -> b转换和b -> b -> Number比较器函数在两个as 上产生一个比较器.我们可以像这样用Ramda创建它:
var on = R.curry(function(map, cmp) {
return R.useWith(cmp, map, map);
return R.useWith(cmp, [map, map]); // since Ramda >0.18
});
or- 就像||,但数字不仅限于布尔人R.or.这可以用于将两个比较器链接在一起,如果第一个得到0(相等),则仅调用第二个比较器.或者,thenBy可以使用类似的库.但是我们自己来定义它:
var or = R.curry(function(fst, snd, a, b) {
return fst(a, b) || snd(a, b);
});
negate - 反转比较的函数:
function negate(cmp) {
return R.compose(R.multiply(-1), cmp);
}
现在,配备这些我们只需要我们的比较函数(自然排序是你找到的那个的改编版本,另见排序数组元素(带数字的字符串),自然排序更多):
var NUMBER_GROUPS = /(-?\d*\.?\d+)/g;
function naturalCompare(a, b) {
var aa = String(a).split(NUMBER_GROUPS),
bb = String(b).split(NUMBER_GROUPS),
min = Math.min(aa.length, bb.length);
for (var i = 0; i < min; i++) {
var x = aa[i].toLowerCase(),
y = bb[i].toLowerCase();
if (x < y) return -1;
if (x > y) return 1;
i++;
if (i >= min) break;
var z = parseFloat(aa[i]) - parseFloat(bb[i]);
if (z != 0) return z;
}
return aa.length - bb.length;
}
function stringCompare(a, b) {
a = String(a); b = String(b);
return +(a>b)||-(a<b);
}
function numberCompare(a, b) {
return a-b;
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以准确地构建您想要的对象的比较:
fn = R.sort(or(on(R.prop("name"), naturalCompare),
on(R.prop("number_of_reqs"), negate(numberCompare))));
fn(arr)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3909 次 |
| 最近记录: |