我正在根据存储在其中的变量对对象列表进行排序。让我们将变量命名为“ sortCriteria”
不同对象的“ sortCriteria”值的样本集:
400、329、529,“ String1”,678,“ String2”,588,“ String3”,“ String1”,201,“ String2”
因此,基本上我可以在“ sortCriteria”中获得4种值:
1.数值
2. String1
3. String2
4. String3
现在,我必须对数据进行排序,以使数字数据具有最高优先级,然后是“ String1”,然后是“ String2”,然后是“ String3”。即
(数字>字符串1>字符串2>字符串3)的优先级
请注意,在输出中,所有这些数字值应按排序顺序。
因此,样本数据的排序顺序为-
201、329、400、529、588、678,“ String1”,“ String1”,“ String2”,“ String2”,“ String3”。
另外,如果多个对象具有相同的“ sortCriteria”值,则应保留其顺序。
例如。
假设我有两个对象的“ sortCriteria”值相同
对象1:205,
对象2:205。
然后,按照排序的顺序,Object1应该位于Object2之前。
我当前对特定逻辑进行排序的JavaScript实现如下所示:
function mySortRule(a, b) {
var value1 = a[1], value2 = b[1];
var value1Priority = getPriorityOf(value1);
var value2Priority = getPriorityOf(value2);
return value1Priority - value2Priority;
}
function getPriorityOf(value) {
var priority;
if(value!="String1" && value!="String2" && value!="String3") {
priority = value;
}
else if(value == "String1") {
priority = Number.MAX_VALUE-2;
}
else if(value == "String2") {
priority = Number.MAX_VALUE-1;
}
else if(value == "String3") {
priority = Number.MAX_VALUE;
}
return priority;
}
sortCriteriaArray.sort(mySortRule);
sortCriteriaArray [i]值采用以下格式: [“ indexOfObject”,“ sortCriteria”]
此解决方案虽然可行,但并不能保持对象顺序。另外,我也不认为这是个好方法,因为-
1.明天,假设我们必须使用其他类型的字符串。在这种情况下,我们将不得不在getPriorityOf()函数中更改这些条件语句。
2.对我来说,使用“ Number.MAX_VALUE”设置优先级似乎很麻烦。
有没有更好的方法可以实现这一目标?
答案 0 :(得分:0)
看看我的解决方案并检查是否合适:
// Array
const arr = [400, 329, 529, "String1", 678, "String2", 588, "String3", "String1", 201, "String2"];
// Filter methods
const isNumber = (item) => !isNaN(item);
const checkString = (str) => (item) => item === str;
// Sort/Config method
const sortPriority = () => {
return [
...arr.filter(isNumber).sort((a, b) => a - b),
...arr.filter(checkString("String1")),
...arr.filter(checkString("String2")),
...arr.filter(checkString("String3")),
]
}
console.log(sortPriority());
答案 1 :(得分:0)
将比较测试排列为字典式的,首先在类型上(分配优先级索引,例如数字:0,字符串:1),然后在值上确定关系。这是干净且可扩展的。
要保留顺序,您需要使用稳定的排序算法,例如MergeSort。
或者,如果您不打算添加其他类型,请按照下列步骤操作:
扫描列表,并(稳定地)拆分为带有数字的子列表和包含字符串的另一个子列表;
对子列表进行排序并将其串联。
答案 2 :(得分:0)
鉴于您的字符串数量少且固定,您可以使用对象作为优先级的字典而不是getPriorityOf
来构建复合排序规则,而不必使用{{1 }}。您可以按照给定字符串的顺序或默认值零(假设数字为最高优先级)来选择对象,然后按数值排序。
MAX_VALUE
var data = [400, 329, 529, "String1", 678, "String2", 588, "String3", "String1", 201, "String2"],
order = { String1: 1, String2: 2, String3: 3 };
data.sort((a, b) => (order[a] || 0) - (order[b] || 0) || a - b);
console.log(data);
不幸的是,.as-console-wrapper { max-height: 100% !important; top: 0; }
不能保证稳定,尽管实际上经常是这样。另请参见About the stability of the algorithm used by V8 engine
如果它在您的环境中不稳定,则可以使用WeakMap
模拟稳定排序来存储原始位置。
您要求稳定性的事实意味着,您确实有一些要按某个字段排序的对象。我假设该字段称为Array.sort
。请注意,算法没有使用data
属性,在此示例中,它只是为了证明订单的稳定性。
index
var data = [{ index: 0, data: 400 }, { index: 1, data: 329 }, { index: 2, data: 529 }, { index: 3, data: "String1" }, { index: 4, data: 678 }, { index: 5, data: "String2" }, { index: 6, data: 588 }, { index: 7, data: "String3" }, { index: 8, data: "String1" }, { index: 9, data: 201 }, { index: 10, data: "String2" }],
indices = new WeakMap(data.map((o, i) => [o, i])),
order = { String1: 1, String2: 2, String3: 3 };
data.sort((a, b) =>
(order[a.data] || 0) - (order[b.data] || 0) || // get priority ordering
a.data - b.data || // order by number
indices.get(a) - indices.get(b) // keep same values in order
);
console.log(data);
答案 3 :(得分:0)
function mySortRule(a, b) {
function getPriorityOf(value) {
// priority order..
return [Boolean, Number, String, Array, Object, Function]
.reverse().indexOf(value.constructor);
}
// smallest first..
return getPriorityOf(a) == getPriorityOf(b) ?
(a.valueOf() == b.valueOf() ?
0 :
(a.valueOf() > b.valueOf() ? 1 : -1)) :
getPriorityOf(b) - getPriorityOf(a)
}
var sortCriteriaArray =
[400, 329, 529, "String1", 678, "String2", 588, "String3", "String1", 201, "String2"];
sortCriteriaArray.sort(mySortRule);
// -> [201, 329, 400, 529, 588, 678, "String1", "String1", "String2", "String2", "String3"]
(假设每个数组元素都不为null或未定义)