如何根据优先级对不同类型的数据进行排序?

时间:2019-01-22 13:52:45

标签: javascript algorithm sorting

我正在根据存储在其中的变量对对象列表进行排序。让我们将变量命名为“ 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”设置优先级似乎很麻烦。
有没有更好的方法可以实现这一目标?

4 个答案:

答案 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或未定义)