无法使用javascript默认排序同时按2个字段排序?
我尝试按2个字段进行排序,这样,如果字段1不可用,则改为按字段2进行排序 字段1下的代码有效,但字段2无效。显然,默认排序并没有对所有元素进行彻底的比较,只有几个元素。我应该放弃默认排序并构建自己的排序吗 以下是已编辑的jsbin,其中包含当前输出与预期输出:无法使用javascript默认排序同时按2个字段排序?,javascript,sorting,Javascript,Sorting,我尝试按2个字段进行排序,这样,如果字段1不可用,则改为按字段2进行排序 字段1下的代码有效,但字段2无效。显然,默认排序并没有对所有元素进行彻底的比较,只有几个元素。我应该放弃默认排序并构建自己的排序吗 以下是已编辑的jsbin,其中包含当前输出与预期输出: 我将删除旧的代码示例,因为我们有一个更清晰的jsbin。您可以创建一个函数,根据提供的字段属性比较两个对象a、b const data=[{age:0,title:“a”,},{age:5,title:“b”,},{age:“用户未输入
我将删除旧的代码示例,因为我们有一个更清晰的jsbin。您可以创建一个函数,根据提供的
字段
属性比较两个对象a、b
const data=[{age:0,title:“a”,},{age:5,title:“b”,},{age:“用户未输入”,title:“fghetwe”,},{age:“奇怪数据”,title:“e”,},{age:5,title:“rtyera”,},{age:“用户未输入”,title:“e”,},{age:1,title:“c”,},{title:“rtyera”,{title:“d”,},{age:2,title:“c”,},{age:null,title:“d”,},{age:[3],title:“c”,},{age:7,title:“c”,},{age:8,title:“a”,},{age:5,title:“h”,},{title:“ayrtyery”,},},{age:1,title:“a”,},{title:“f”,};
//检查值是否为null或未定义
const isNullish=v=>v==null | | typeof v==='undefined'
常量isNullOrNaN=v=>v==null | | isNaN(v)
//根据字段类型发送至comapre 2
功能比较(a、b、字段){
常量aValue=a[field],bValue=b[field];
返回isNullish(bValue)-isNullish(aValue)
||isNullOrNaN(bValue)-isNullOrNaN(aValue)
||(aValue>B值?1:aValue
输入.排序((a,b)=>
比较(a,b,主要排序)|比较(a,b,次要排序)
)
log(customSort(数据,'age','title'))
log(customSort(数据,'title','age'))
请添加一个输入数组样本和两个可选数据字段的预期输出。@adiga那么这不是不可能的吗?我只是想知道这是否是一个完整的解决方案。如果没有看到输入样本、要排序的字段和预期输出,就不清楚您在问什么。预期输出是什么在jsbin中对数据进行排序后?@adiga ok构建了一个新的示例,其中包含了更多预期的输出。感谢您的回答。不幸的是,字段和值都不在我的控制范围内,我不知道用户将按什么进行排序,以及它们是什么类型。我需要首先检查isNaN,尽管我想我可以在排序之前进行检查?它可能有多种类型,但为了理智起见,我将其限制为数字和字符串。@Harry,您也可以直接检查字段本身,而不是比较如果(字段=='age'|字段=='otherNumberField'){//number logic}中的字段本身{//string logic}
年龄只是一个例子,它可以是任何东西。例如,它可以是'yearssubscribed',我事先不知道。在比较过程中进行检查似乎对我不太有效。aValue可以是未定义的或字符串,但实际上可能是一个数字。这不起作用:(isNaN(parseFloat(attr))和&isNaN(parseFloat(bAttr))(!isNaN(attr)和&isNaN(bAttr))
这就是为什么我会遇到这种情况。@Harry我已经更新了。现在它使用了
和三元运算符来比较值。这对字符串和数字有效。这可能会有效。再次感谢你,我编辑了这个示例来打破排序:你能看看这个吗?
var data = [{
age: 0,
title: "a",
}, {
age: 5,
title: "b",
}, {
age: "user did not enter",
title: "fghetwe",
}, {
age: "strange data",
title: "e",
}, {
age: 5,
title: "rtyera",
}, {
age: "user did not enter",
title: "c",
}, {
age: "user did not enter",
title: "e",
}, {
age: 1,
title: "c",
}, {
title: "rtyera",
}, {
age: 1,
title: "a",
}, {
title: "d",
}, {
age: 2,
title: "c",
}, {
age: null,
title: "d",
}, {
age: [3],
title: "c",
}, {
age: 7,
title: "c",
}, {
age: 8,
title: "a",
}, {
age: 5,
title: "h",
}, {
title: "ayrtyery",
}, {
title: "a",
}, {
age: 1,
title: "a",
}, {
title: "f",
}]
var primarySort = "age";
var secondarySort = "title"
var list = Backbone.Collection.extend({
// Reference to this collection's model.
comparator: function (a, b) {
let attr = a.get(primarySort)
let bAttr = b.get(primarySort)
if (Array.isArray(attr)) attr = attr.join(" ")
if (Array.isArray(bAttr)) bAttr = bAttr.join(" ")
if ((isNaN(parseFloat(attr)) && !isNaN(parseFloat(bAttr)))) {
return -1
}
if (!isNaN(parseFloat(attr)) && isNaN(parseFloat(bAttr))) {
return 1
}
if ((!isNaN(attr) && isNaN(bAttr))) {
return -1
}
if ((isNaN(attr) && !isNaN(bAttr))) {
return 1
}
if (attr != null && bAttr != null && !isNaN(parseFloat(attr)) && !isNaN(parseFloat(bAttr))) {
attr = parseFloat(attr)
bAttr = parseFloat(bAttr)
if (attr > bAttr) return 1
if (attr < bAttr) return -1
if (attr == bAttr) {
if (a.get(secondarySort) > b.get(secondarySort)) {
return 1
}
else if (a.get(secondarySort) < b.get(secondarySort)) {
return -1
}
}
}
if ((!attr && attr != 0) && (bAttr || bAttr == 0)) {
return -1
}
if ((!bAttr && bAttr != 0) && (attr || attr == 0)) {
return 1
}
if (!attr && attr != 0 && !bAttr && bAttr != 0) {
if (a.get(secondarySort) > b.get(secondarySort)) {
return 1
}
else if (a.get(secondarySort) < b.get(secondarySort)) {
return -1
}
return 0
}
if (isNaN(attr) || isNaN(bAttr)) {
if (attr > bAttr) return 1
if (attr < bAttr) return -1
return 0
}
if (a.get(secondarySort) > b.get(secondarySort)) {
return 1
}
else if (a.get(secondarySort) < b.get(secondarySort)) {
return -1
}
else {
return 0
}
},
})
console.log(new list(data).toJSON())
document.getElementById("first").innerHTML += JSON.stringify(new list(data).toJSON(), undefined, 2)
// expected
var firstexpected = [
{
"title": "a"
},
{
"title": "ayrtyery"
},
{
"age": null,
"title": "d"
},
{
"title": "d"
},
{
"title": "f"
},
{
"title": "rtyera"
},
{
"age": "user did not enter",
"title": "c"
},
{
"age": "strange data",
"title": "e"
},
{
"age": "user did not enter",
"title": "e"
},
{
"age": "user did not enter",
"title": "fghetwe"
},
{
"age": 0,
"title": "a"
},
{
"age": 1,
"title": "a"
},
{
"age": 1,
"title": "a"
},
{
"age": 1,
"title": "c"
},
{
"age": 2,
"title": "c"
},
{
"age": [
3
],
"title": "c"
},
{
"age": 5,
"title": "b"
},
{
"age": 5,
"title": "h"
},
{
"age": 5,
"title": "rtyera"
},
{
"age": 7,
"title": "c"
},
{
"age": 8,
"title": "a"
}
]
primarySort = "title";
secondarySort = "age"
document.getElementById("second").innerHTML += JSON.stringify(new list(data).toJSON(), undefined, 2)
var secondexpected = [
{
"title": "a"
},
{
"age": 0,
"title": "a"
},
{
"age": 1,
"title": "a"
},
{
"age": 1,
"title": "a"
},
{
"age": 8,
"title": "a"
},
{
"title": "ayrtyery"
},
{
"age": 5,
"title": "b"
},
{
"age": "user did not enter",
"title": "c"
},
{
"age": 1,
"title": "c"
},
{
"age": 2,
"title": "c"
},
{
"age": [
3
],
"title": "c"
},
{
"age": 7,
"title": "c"
},
{
"title": "d"
},
{
"age": null,
"title": "d"
},
{
"age": "strange data",
"title": "e"
},
{
"age": "user did not enter",
"title": "e"
},
{
"title": "f"
},
{
"age": "user did not enter",
"title": "fghetwe"
},
{
"age": 5,
"title": "h"
},
{
"title": "rtyera"
},
{
"age": 5,
"title": "rtyera"
},
]
{
"age": "user did not enter",
"title": "fghetwe"
},
{
"age": "user did not enter",
"title": "c"
},
{
"age": "user did not enter",
"title": "e"
},