根据多个字段在JavaScript中对数据进行排序

huangapple go评论107阅读模式
英文:

Sort data based on multiple fields in javascript

问题

我有一个需求要对数据进行排序,以下是我的数据样式。

[
  {
    "id": "course1",
    "type": "course",
    "sequence": 1
  },
  {
    "id": "course2",
    "type": "course",
    "sequence": 2
  },
  {
    "id": "course1_chapter1",
    "type": "chapter",
    "sequence": 1,
    "course": {
      "id": "course1",
      "sequence": 1
    }
  },
  ...
]

现在我的要求是首先根据类型排序,顺序应为课程、章节、课程,然后根据顺序排序。所以我的最终期望结果如上所示的数据。

course1, course2, course1_chapter1, course1_chapter2, course2_chapter1, course1_chapter1_lesson1, course1_chapter1_lesson2, course1_chapter1_lesson2, course1_chapter2_lesson1

我提到的示例数据已经按排序方式排列,但在实时场景中,我会收到未排序的数据。

目前我只是按类型使用得分进行了排序。
我可以将数据拆分为不同的变量进行排序,最后将排序后的数据放入单个变量中,但我想知道是否有我可能不知道的高级选项。
英文:

I have a requirement to sort the data and below is what my data looks like.

[
  {
    "id": "course1",
    "type": "course",
    "sequence": 1
  },
  {
    "id": "course2",
    "type": "course",
    "sequence": 2
  },
  {
    "id": "course1_chapter1",
    "type": "chapter",
    "sequence": 1,
    "course": {
      "id": "course1",
      "sequence": 1
    }
  },
  {
    "id": "course1_chapter2",
    "type": "chapter",
    "sequence": 2,
    "course": {
      "id": "course1",
      "sequence": 1
    }
  },
  {
    "id": "course2_chapter1",
    "type": "chapter",
    "sequence": 1,
    "course": {
      "id": "course1",
      "sequence": 2
    }
  },
  {
    "id": "course1_chapter1_lesson1",
    "type": "lesson",
    "sequence": 1,
    "course": {
      "id": "course1",
      "sequence": 1
    },
    "chapter": {
      "id": "chapter1",
      "sequence": 1
    }
  },
  {
    "id": "course1_chapter1_lesson2",
    "type": "lesson",
    "sequence": 2,
    "course": {
      "id": "course1",
      "sequence": 1
    },
    "chapter": {
      "id": "chapter1",
      "sequence": 1
    }
  },
  {
    "id": "course1_chapter2_lesson1",
    "type": "lesson",
    "sequence": 1,
    "course": {
      "id": "course1",
      "sequence": 1
    },
    "chapter": {
      "id": "chapter1",
      "sequence": 2
    }
  }
]

Now my requirement is to sort the data based on type 1st where the order should be course, chapter, and lesson, and then order based on the sequence. So my final outcome expectation is as per the above data

course1, course2, course1_chapter1, course1_chapter2, course2_chapter1, course1_chapter1_lesson1, course1_chapter1_lesson2, course1_chapter1_lesson2, course1_chapter2_lesson1

The sample data which I have mentioned is already in sorted manner but in real time scenario, I get unsorted data.

right now I have sorted just by Type using the score.
I could do the sorting by splitting the data into different variable and finally get the sorted data into single variable but would like to know if there is any advance option which I might not be aware.

答案1

得分: 2

你可以在你的 sort 回调函数中使用单个表达式:

const data = [{"id": "course1","type": "course","sequence": 1},{"id": "course2","type": "course","sequence": 2},{"id": "course1_chapter1","type": "chapter","sequence": 1,"course": {"id": "course1","sequence": 1}},{"id": "course1_chapter2","type": "chapter","sequence": 2,"course": {"id": "course1","sequence": 1}},{"id": "course2_chapter1","type": "chapter","sequence": 1,"course": {"id": "course1","sequence": 2}},{"id": "course1_chapter1_lesson1","type": "lesson","sequence": 1,"course": {"id": "course1","sequence": 1},"chapter": {"id": "chapter1","sequence": 1}},{"id": "course1_chapter1_lesson2","type": "lesson","sequence": 2,"course": {"id": "course1","sequence": 1},"chapter": {"id": "chapter1","sequence": 1}},{"id": "course1_chapter2_lesson1","type": "lesson","sequence": 1,"course": {"id": "course1","sequence": 1},"chapter": {"id": "chapter1","sequence": 2}}];

const result = data.sort((a, b) =>
    !b.course - !a.course || !b.chapter - !a.chapter
    || a.course?.sequence  - b.course?.sequence 
    || a.chapter?.sequence - b.chapter?.sequence 
    || a.sequence - b.sequence
).map(a => a.id);

console.log(result);

表达式的第一行检查两个项是否具有不同的粒度(例如,一个具有章节,另一个没有)。如果这个条件为真,则优先考虑具有较少粒度的项。

如果该条件为假(即它们具有相同的粒度),则比较可用的序列。

英文:

You can use a single expression in your sort callback:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const data = [{&quot;id&quot;: &quot;course1&quot;,&quot;type&quot;: &quot;course&quot;,&quot;sequence&quot;: 1},{&quot;id&quot;: &quot;course2&quot;,&quot;type&quot;: &quot;course&quot;,&quot;sequence&quot;: 2},{&quot;id&quot;: &quot;course1_chapter1&quot;,&quot;type&quot;: &quot;chapter&quot;,&quot;sequence&quot;: 1,&quot;course&quot;: {&quot;id&quot;: &quot;course1&quot;,&quot;sequence&quot;: 1}},{&quot;id&quot;: &quot;course1_chapter2&quot;,&quot;type&quot;: &quot;chapter&quot;,&quot;sequence&quot;: 2,&quot;course&quot;: {&quot;id&quot;: &quot;course1&quot;,&quot;sequence&quot;: 1}},{&quot;id&quot;: &quot;course2_chapter1&quot;,&quot;type&quot;: &quot;chapter&quot;,&quot;sequence&quot;: 1,&quot;course&quot;: {&quot;id&quot;: &quot;course1&quot;,&quot;sequence&quot;: 2}},{&quot;id&quot;: &quot;course1_chapter1_lesson1&quot;,&quot;type&quot;: &quot;lesson&quot;,&quot;sequence&quot;: 1,&quot;course&quot;: {&quot;id&quot;: &quot;course1&quot;,&quot;sequence&quot;: 1},&quot;chapter&quot;: {&quot;id&quot;: &quot;chapter1&quot;,&quot;sequence&quot;: 1}},{&quot;id&quot;: &quot;course1_chapter1_lesson2&quot;,&quot;type&quot;: &quot;lesson&quot;,&quot;sequence&quot;: 2,&quot;course&quot;: {&quot;id&quot;: &quot;course1&quot;,&quot;sequence&quot;: 1},&quot;chapter&quot;: {&quot;id&quot;: &quot;chapter1&quot;,&quot;sequence&quot;: 1}},{&quot;id&quot;: &quot;course1_chapter2_lesson1&quot;,&quot;type&quot;: &quot;lesson&quot;,&quot;sequence&quot;: 1,&quot;course&quot;: {&quot;id&quot;: &quot;course1&quot;,&quot;sequence&quot;: 1},&quot;chapter&quot;: {&quot;id&quot;: &quot;chapter1&quot;,&quot;sequence&quot;: 2}}];
const result = data.sort((a, b) =&gt;
!b.course - !a.course || !b.chapter - !a.chapter
|| a.course?.sequence  - b.course?.sequence 
|| a.chapter?.sequence - b.chapter?.sequence 
|| a.sequence - b.sequence
).map(a =&gt; a.id);
console.log(result);

<!-- end snippet -->

The first line of the expression checks if both items have a different granularity (for example, one has a chapter, the other doesn't). If this condition is true, then precedence is given to the item that has least granularity.

If that condition is false (i.e. they have the same granularity), then the available sequences are compared.

答案2

得分: 0

sort 函数以一个比较函数作为参数,该函数必须在其第一个参数小于第二个参数时返回负值,在其第一个参数大于第二个参数时返回正值,如果它们相等则返回零。

您可以通过比较类型的重要性(课程比章节更重要)以及比较给定类型内的序列号来在您的情况下使用这种技术:

const types = ["course", "chapter", "lesson"];
data.sort(function(a, b) {
  if (a.type !== b.type) return types.indexOf(a.type) - types.indexOf(b.type);
  for (var t of types) {
    if (t === a.type) return a.sequence - b.sequence;
    var d = a[t].sequence - b[t].sequence;
    if (d !== 0) return d;
  }
});
英文:

The sort function takes as argument a comparison function that must return a negative value if its first argument is less than its second, a positive value if its first argument is greater than its second, and zero if they are equal.

You can use this technique in your case by comparing the significance of types (course is more significant than chapter) and by comparing the sequence numbers within a given type:

const types = [&quot;course&quot;, &quot;chapter&quot;, &quot;lesson&quot;];
data.sort(function(a, b) {
  if (a.type !== b.type) return types.indexOf(a.type) - types.indexOf(b.type);
  for (var t of types) {
    if (t === a.type) return a.sequence - b.sequence;
    var d = a[t].sequence - b[t].sequence;
    if (d !== 0) return d;
  }
});

答案3

得分: 0

你可以使用Array#sort方法的回调函数来指定排序项的顺序。

回调函数在以下情况下返回 -1,表示项 a 应该排在 b 之前,返回 1 表示 b 应该排在 a 之前。

array.sort(function (a, b) {
    if (a.type !== b.type) {
        if (a.type === "course") return -1;
        if (b.type === "course") return 1;
        if (a.type === "chapter") return -1;
        if (b.type === "chapter") return 1;
    }
    if (a.sequence > b.sequence) return 1;
    return -1;
});

在使用 sort 函数时要小心,因为它会原地排序数组,这意味着你将失去原始未排序的数组。如果你需要保留原始数组和排序后的版本,你可以使用各种方法创建数组的克隆。

以下是演示这种排序对数据的影响的代码片段:

var array = [

    {
        "id": "course2",
        "type": "course",
        "sequence": 2
    },
    {
        "id": "course1_chapter1",
        "type": "chapter",
        "sequence": 1,
        "course": {
            "id": "course1",
            "sequence": 1
        }
    },

    {
        "id": "course1_chapter2",
        "type": "chapter",
        "sequence": 2,
        "course": {
            "id": "course1",
            "sequence": 1
        }
    },
    {
        "id": "course1",
        "type": "course",
        "sequence": 1
    },
    {
        "id": "course1_chapter1_lesson2",
        "type": "lesson",
        "sequence": 2,
        "course": {
            "id": "course1",
            "sequence": 1
        },
        "chapter": {
            "id": "chapter1",
            "sequence": 1
        }
    },
    {
        "id": "course2_chapter1",
        "type": "chapter",
        "sequence": 1,
        "course": {
            "id": "course1",
            "sequence": 2
        }
    },
    {
        "id": "course1_chapter1_lesson1",
        "type": "lesson",
        "sequence": 1,
        "course": {
            "id": "course1",
            "sequence": 1
        },
        "chapter": {
            "id": "chapter1",
            "sequence": 1
        }
    },

    {
        "id": "course1_chapter2_lesson1",
        "type": "lesson",
        "sequence": 1,
        "course": {
            "id": "course1",
            "sequence": 1
        },
        "chapter": {
            "id": "chapter1",
            "sequence": 2
        }
    }
]

console.log("Original Array: ", array);

array.sort(function (a, b) {
    if (a.type !== b.type) {
        if (a.type === "course") return -1;
        if (b.type === "course") return 1;
        if (a.type === "chapter") return -1;
        if (b.type === "chapter") return 1;
    }
    if (a.sequence > b.sequence) return 1;

    return -1;
});

console.log("Ordered Array: ", array);
英文:

You can use the callback function of the Array#sort method, which specifies how to order items.

The callback returns -1 when item a should be placed before b, and 1 when b should be placed before a.

array.sort(function (a, b) {
if (a.type !== b.type) {
if (a.type === &quot;course&quot;) return -1;
if (b.type === &quot;course&quot;) return 1;
if (a.type === &quot;chapter&quot;) return -1;
if (b.type === &quot;chapter&quot;) return 1;
}
if (a.sequence &gt; b.sequence) return 1;
return -1;
});

You should be careful when using the sort function, because it sorts the array in-place, meaning that you will lose the original unsorted array. If you need to keep the original and the sorted version, you can create a clone of the array using a variety of methods.

Here's a snippet demonstrating the effects of this sort on your data:

<!-- begin snippet: js hide: true console: true babel: false -->

<!-- language: lang-js -->

var array = [
{
&quot;id&quot;: &quot;course2&quot;,
&quot;type&quot;: &quot;course&quot;,
&quot;sequence&quot;: 2
},
{
&quot;id&quot;: &quot;course1_chapter1&quot;,
&quot;type&quot;: &quot;chapter&quot;,
&quot;sequence&quot;: 1,
&quot;course&quot;: {
&quot;id&quot;: &quot;course1&quot;,
&quot;sequence&quot;: 1
}
},
{
&quot;id&quot;: &quot;course1_chapter2&quot;,
&quot;type&quot;: &quot;chapter&quot;,
&quot;sequence&quot;: 2,
&quot;course&quot;: {
&quot;id&quot;: &quot;course1&quot;,
&quot;sequence&quot;: 1
}
},
{
&quot;id&quot;: &quot;course1&quot;,
&quot;type&quot;: &quot;course&quot;,
&quot;sequence&quot;: 1
},
{
&quot;id&quot;: &quot;course1_chapter1_lesson2&quot;,
&quot;type&quot;: &quot;lesson&quot;,
&quot;sequence&quot;: 2,
&quot;course&quot;: {
&quot;id&quot;: &quot;course1&quot;,
&quot;sequence&quot;: 1
},
&quot;chapter&quot;: {
&quot;id&quot;: &quot;chapter1&quot;,
&quot;sequence&quot;: 1
}
},
{
&quot;id&quot;: &quot;course2_chapter1&quot;,
&quot;type&quot;: &quot;chapter&quot;,
&quot;sequence&quot;: 1,
&quot;course&quot;: {
&quot;id&quot;: &quot;course1&quot;,
&quot;sequence&quot;: 2
}
},
{
&quot;id&quot;: &quot;course1_chapter1_lesson1&quot;,
&quot;type&quot;: &quot;lesson&quot;,
&quot;sequence&quot;: 1,
&quot;course&quot;: {
&quot;id&quot;: &quot;course1&quot;,
&quot;sequence&quot;: 1
},
&quot;chapter&quot;: {
&quot;id&quot;: &quot;chapter1&quot;,
&quot;sequence&quot;: 1
}
},
{
&quot;id&quot;: &quot;course1_chapter2_lesson1&quot;,
&quot;type&quot;: &quot;lesson&quot;,
&quot;sequence&quot;: 1,
&quot;course&quot;: {
&quot;id&quot;: &quot;course1&quot;,
&quot;sequence&quot;: 1
},
&quot;chapter&quot;: {
&quot;id&quot;: &quot;chapter1&quot;,
&quot;sequence&quot;: 2
}
}
]
console.log(&quot;Original Array: &quot;, array);
array.sort(function (a, b) {
if (a.type !== b.type) {
if (a.type === &quot;course&quot;) return -1;
if (b.type === &quot;course&quot;) return 1;
if (a.type === &quot;chapter&quot;) return -1;
if (b.type === &quot;chapter&quot;) return 1;
}
if (a.sequence &gt; b.sequence) return 1;
return -1;
});
console.log(&quot;Ordered Array: &quot;, array);

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年8月5日 15:00:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76840485.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定