iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
📝

Sorting an array excluding the first n elements in JavaScript

に公開

This is a note on how to sort only from the second element onwards in a JavaScript array.

repl: https://repl.it/@anozon/sortbody#index.ts

Array to be Sorted

// js
const elems = [
  { name: 'primary', count: 10 }, // Don't sort this!
  { name: 'b', count: 2 },
  { name: 'd', count: 12 },
  { name: 'a', count: 1 },
  { name: 'c', count: 11 },
]

// ts
type Elem = {
  name: string
  count: number
}

const elems: Elem[] = [
  { name: 'primary', count: 10 },
  { name: 'b', count: 2 },
  { name: 'd', count: 12 },
  { name: 'a', count: 1 },
  { name: 'c', count: 11 },
]

Sorting Everything Except the First Element

function sortBody(arr0: Elem[]) {
  if (arr0.length <= 2) return arr0
  const [head, ...arr] = arr0

  arr.sort((a, b) => a.count - b.count)
  return [head, ...arr]
}
sortBody(elems)
// [ { name: 'primary', count: 10 },
//   { name: 'a', count: 1 },
//   { name: 'b', count: 2 },
//   { name: 'c', count: 11 },
//   { name: 'd', count: 12 } ]

Sorting Only from the nth Element Onwards

const arrSplit = <T>(aa: T[], n: number): [T[], T[]] => [
  aa.slice(0, n),
  aa.slice(n),
]
function sortBodyN(arr0: Elem[], n: number) {
  const [heads, arr] = arrSplit(arr0, n)

  arr.sort((a, b) => a.count - b.count)
  return [...heads, ...arr]
}
const sortBody = (arr0: Elem[]) => sortBodyN(arr0, 0)

sortBodyN(elems, 2)
// [ { name: 'primary', count: 10 },
//   { name: 'b', count: 2 },
//   { name: 'a', count: 1 },
//   { name: 'c', count: 11 },
//   { name: 'd', count: 12 } ]

When Using Lodash

Since _.sortBy(arr, [(o, i) => /* */ ]) did not allow retrieving the initial index, this is a method where you temporarily attach the index and then revert it at the end.

import { sortBy } from 'lodash'
function sortBodyLoN(arr: Elem[], n: number) {
  return sortBy(
    arr.map((v, i) => [v, i]),
    [([o, i]) => (i < n ? i : Infinity), '0.count']
  ).map((v) => v[0])
}
import { sortBy } from 'lodash'

const withKey = <T>(a: T[]) => a.map((v, i): [number, T] => [i, v])
// const withKey = <T>(a: T[]) => Object.entries(a).map(([i, v]): [number, T] => [Number(i), v])

function sortBodyLo(arr: Elem[], n: number = 0) {
  return sortBy(withKey(arr), [
    ([i, o]) => (i < n ? i : Infinity),
    '1.count',
  ]).map((v) => v[1])
}

In ([i, o]) => (i < n ? i : Infinity),, sorting is performed only for elements from the nth row onwards (while maintaining the order of the preceding ones).

Regarding Lodash, I tend to avoid it unless I'm using it heavily due to TreeShaking concerns; however, it's easy to write complex sorting conditions, so I often use it.

GitHubで編集を提案

Discussion