配列をソートするには
配列(リスト)を昇順・降順やキー指定で並べ替える基本形を各言語で示す。
破壊的か非破壊的か、JavaScript の既定が辞書順になる罠までを扱う。
公開: 更新:
各言語見出しの横のバッジは検証状態を表す。実行確認済みはコードを実際に実行して確認したもの、静的確認は構文と公式 API ドキュメントで確認したものである。
Python 実行確認済み
nums = [3, 1, 10, 2]
print(sorted(nums)) # 新しいリストを返す → [1, 2, 3, 10]
nums.sort(reverse=True) # 元のリストをその場で降順に
words = ["banana", "apple"]
print(sorted(words, key=len)) # キー関数で基準を指定 → ['apple', 'banana']sorted は新しいリストを返し、list.sort は元のリストをその場で並べ替える。
並べ替えの基準を変えたいときは key に関数を渡し、降順にするなら reverse=True を指定する。
JavaScript 実行確認済み
const nums = [3, 1, 10, 2];
console.log([...nums].sort((a, b) => a - b)); // 数値順 → [1, 2, 3, 10]
console.log(nums.sort()); // 既定は文字列順 → [1, 10, 2, 3]Array.prototype.sort は比較関数を渡さないと要素を文字列に変換して比較するため、数値はそのままだと辞書順になる。
数値順にするには (a, b) => a - b を渡す。
sort は破壊的なので、元の配列を残すならスプレッドでコピーしてから並べ替える。
TypeScript 実行確認済み
const nums: number[] = [3, 1, 10, 2];
const asc: number[] = [...nums].sort((a, b) => a - b);
console.log(asc); // [1, 2, 3, 10]使い方は JavaScript と同じで、比較関数の引数と戻り値に型が付くだけである。
sort は元の配列を破壊的に並べ替えるため、number[] を保ちたいならスプレッドでコピーしてから呼ぶ。
Go 静的確認
package main
import (
"fmt"
"sort"
)
func main() {
nums := []int{3, 1, 10, 2}
sort.Ints(nums) // 昇順(破壊的)→ [1 2 3 10]
fmt.Println(nums)
sort.Slice(nums, func(i, j int) bool { return nums[i] > nums[j] }) // 任意の基準で降順
fmt.Println(nums)
}sort.Ints や sort.Strings は基本型のスライスをその場で昇順に並べ替える。
独自の基準や降順にするときは sort.Slice に比較関数を渡す。
いずれも元のスライスを破壊的に変更する。
Rust 静的確認
fn main() {
let mut nums = vec![3, 1, 10, 2];
nums.sort(); // 破壊的に昇順 → [1, 2, 3, 10]
nums.sort_by(|a, b| b.cmp(a)); // 比較関数で降順
println!("{:?}", nums);
}Vec::sort は要素をその場で昇順に並べ替える破壊的メソッドである。
降順や独自基準にするときは sort_by に比較クロージャを渡す。
元の順序を残したいなら clone してから並べ替える。
Java 実行確認済み
import java.util.*;
public class Main {
public static void main(String[] args) {
int[] nums = {3, 1, 10, 2};
Arrays.sort(nums); // 配列を破壊的に昇順
List<Integer> list = new ArrayList<>(List.of(3, 1, 10, 2));
list.sort(Comparator.reverseOrder()); // List を降順
System.out.println(Arrays.toString(nums) + " " + list);
}
}配列は Arrays.sort、List は Collections.sort か list.sort でその場で昇順に並べ替える。
降順や独自基準にするときは Comparator を渡す。
プリミティブの int[] は Comparator を使えないため、降順にするなら Integer[] にするか後で反転する。
C# 静的確認
using System;
using System.Linq;
class Program {
static void Main() {
int[] nums = {3, 1, 10, 2};
Array.Sort(nums); // 破壊的に昇順
var desc = nums.OrderByDescending(x => x).ToArray(); // LINQ は非破壊
Console.WriteLine(string.Join(",", desc));
}
}Array.Sort は配列をその場で昇順に並べ替える破壊的メソッドである。
元の配列を保ちたいときは LINQ の OrderBy / OrderByDescending を使うと新しい列を返す。
キー指定も OrderBy(x => x.Field) で書ける。
つまずき
JavaScript の Array.prototype.sort は、比較関数を渡さないと要素を文字列に変換してから並べ替える。
そのため [3, 1, 10, 2] を既定の sort で並べ替えると、数値順の [1, 2, 3, 10] ではなく辞書順の [1, 10, 2, 3] になるという定番の罠がある。
数値を並べ替えるときは必ず (a, b) => a - b のような比較関数を渡す。
破壊的か非破壊的か
並べ替えには、元の配列をその場で変更する破壊的なもの(JavaScript の sort、Python の list.sort、Go の sort.Ints)と、新しい列を返す非破壊的なもの(Python の sorted)がある。
元の順序を後でも使うなら、破壊的な関数を呼ぶ前にコピーしておくと安全である。