Posted at

# 文系でもわかるElixirのEnum.sortの使い方

More than 1 year has passed since last update.

# 結論

Enum.sort(list,　fn(x, y) -> 条件式 end)

と書いた場合、

「条件式の結果がfalseの場合に前後(xとyの要素)を入れ替える」

と理解すれば使い方としてはOKかと

# 色々やった結果

## サンプルmapリストの準備

```iex(81)> map1 = %{name: "map1", key1: 100, key2: 200}
%{key1: 100, key2: 200, name: "map1"}
iex(82)> map2 = %{name: "map2", key1: 99, key2: 201}
%{key1: 99, key2: 201, name: "map2"}
iex(83)> map3 = %{name: "map3", key1: 101, key2: 199}
%{key1: 101, key2: 199, name: "map3"}
iex(87)> map4 = %{name: "map4", key1: 100, key2: 201}
%{key1: 100, key2: 201, name: "map4"}
iex(90)> list = [map1, map2, map3 ,map4]
[
%{key1: 100, key2: 200, name: "map1"},
%{key1: 99, key2: 201, name: "map2"},
%{key1: 101, key2: 199, name: "map3"},
%{key1: 100, key2: 201, name: "map4"}
]
```

## ソートしてみる

fn(x,y) -> x.key1 < y.key1 key1で昇順（同じ値の場合は結果がfalseなので並べ替えが起こってしまう）

fn(x,y) -> x.key1 <= y.key1 key1で昇順（同じ値の場合に並べ替えが起こらない）

```iex(100)> Enum.sort(list, fn(x,y) -> x.key1 < y.key1  end)
[
%{key1: 99, key2: 201, name: "map2"},
%{key1: 100, key2: 201, name: "map4"},
%{key1: 100, key2: 200, name: "map1"},
%{key1: 101, key2: 199, name: "map3"}
]
iex(101)> Enum.sort(list, fn(x,y) -> x.key1 <= y.key1  end)
[
%{key1: 99, key2: 201, name: "map2"},
%{key1: 100, key2: 200, name: "map1"},
%{key1: 100, key2: 201, name: "map4"},
%{key1: 101, key2: 199, name: "map3"}
]
```

## 第２ソート条件を指定する

fn(x,y) -> x.key1 < y.key1 or ( x.key1 == y.key1 and x.name >= y.name) end)

```iex(111)> Enum.sort(list, fn(x,y) -> x.key1 < y.key1 or ( x.key1 == y.key1 and x.name >= y.name) end)
[
%{key1: 99, key2: 201, name: "map2"},
%{key1: 100, key2: 201, name: "map4"},
%{key1: 100, key2: 200, name: "map1"},
%{key1: 101, key2: 199, name: "map3"}
]
iex(114)> Enum.sort(list, fn(x,y) -> x.key1 <= y.key1 end)
[
%{key1: 99, key2: 201, name: "map2"},
%{key1: 100, key2: 200, name: "map1"},
%{key1: 100, key2: 201, name: "map4"},
%{key1: 101, key2: 199, name: "map3"}
]
```

x.key1 <= y.key1 or ( x.key1 == y.key1 and x.name >= y.name)

としてしまうとx.key1 <= y.key1の時点で結果がtrueになるので第２条件でのソートが行われない

```iex(117)> Enum.sort(list, fn(x, y) -> x.key1 <= y.key1 or ( x.key1 == y.key1 and x.name >= y.name) end)
[
%{key1: 99, key2: 201, name: "map2"},
%{key1: 100, key2: 200, name: "map1"},
%{key1: 100, key2: 201, name: "map4"},
%{key1: 101, key2: 199, name: "map3"}
]
```