🤝
JavaScriptで配列内オブジェクトの値から重複と空の値がない一次元の配列を作る
実装することがあったのでメモです。
[
{
"id": 1,
"category": [0, 10, 11, 13]
},
{
"id": 2,
"category": [12, null]
},
{
"id": 3,
"category": ["", 13]
},
{
"id": 4,
"category": ""
},
]
上記のような配列からcategory
の値を取り出して、null
や空の値を削除した以下のように平坦な配列を作る。
[0, 10, 11, 12, 13]
map()
でcategory
の値のみの配列を作る
まずmap()
でcategory
の値のみの配列を作る。
const array = [
{
"id": 1,
"category": [0, 10, 11, 13]
},
{
"id": 2,
"category": [12, null]
},
{
"id": 3,
"category": ["", 13]
},
{
"id": 4,
"category": ""
},
]
const categories = array.map((item) => item.category)
console.log(categories) //[[0, 10, 11, 13], [12, null], ["", 13], ""]
flat()
でネストした配列を平坦化
配列を平坦化するのに便利なflat()
を使う。
const categories = [
[0, 10, 11, 13],
[12, null],
["", 13],
""
]
const flatCategories = categories.flat()
console.log(flatCategories) //[0, 10, 11, 13, 12, null, "", 13, ""]
filter()
で空の値やnullを削除
数字だけであればfilter(Number.isFinite)
で一気に解決できる。
const flatCategories = [0, 10, 11, 13, 12, null, "", 13, ""]
const filterCategories = flatCategories.filter(Number.isFinite)
console.log(filterCategories) //[0, 10, 11, 13, 12, 13]
文字列など複合した配列の場合は条件を指定してフィルタリングする。
const flatCategories = [0, 10, 11, 13, 12, null, "", 13, "", "aaa", "bbb"]
const filterCategories = flatCategories.filter((item) => item !== "" && item !== undefined && item !== null)
console.log(filterCategories) //[0, 10, 11, 13, 12, 13, "aaa", "bbb"]
空の値やnull、undefinedに加え数値「0」が削除されても構わない場合はfilter(Boolean)
で解決できる。
const flatCategories = [0, 10, 11, 13, 12, null, "", 13, "", "aaa", "bbb"]
const filterCategories = flatCategories.filter(Boolean)
console.log(filterCategories) //[10, 11, 13, 12, 13, "aaa", "bbb"]
sort()
で数字を昇順に並び替える
const filterCategories = [0, 10, 11, 13, 12, 13]
const sortCategories = filterCategories.sort((a, b) => a - b)
console.log(sortCategories) //[0, 10, 11, 12, 13, 13]
Set
で重複を削除
Set
を使えば簡単に重複を削除できる。
const sortCategories = [0, 10, 11, 12, 13, 13]
const newCategories = [...new Set(filterCategories)]
console.log(newCategories) //[0, 10, 11, 13, 12]
まとめて書いてみる
const array = [
{
"id": 1,
"category": [0, 10, 11, 13]
},
{
"id": 2,
"category": [12, null]
},
{
"id": 3,
"category": ["", 13]
},
{
"id": 4,
"category": ""
},
]
const categories = [...new Set(
array
.map((item) => item.category)
.flat()
.filter(Number.isFinite)
.sort((a, b) => a - b)
)]
console.log(categories) //[0, 10, 11, 12, 13]
flatMap()
メソッドを利用する
flatMap()
というメソッドを知った。
これはES2019でflat()
と共に追加されていたもので、配列をマッピングしたあとにフラット化するメソッド。map()
とflat()
を別々にコールするよりわずかに効率的とのこと。
以下のように書き換えられる。
const array = [...]
const categories = [...new Set(
array
.flatMap((item) => item.category)
.filter(Number.isFinite)
.sort((a, b) => a - b)
)]
console.log(categories) //[0, 10, 11, 12, 13]
Set
で重複を削除してからsort()
で並び替える
Set
で重複を削除してからsort()
で並び替えた方がソートする要素が減る。
ChatGPTからパフォーマンスが向上する可能性があるとアドバイスを受けたので、以下のように書き換える。
const array = [...]
const categories = [...new Set(
array
.flatMap((item) => item.category)
.filter(Number.isFinite)
)].sort((a, b) => a - b)
console.log(categories) //[0, 10, 11, 12, 13]
以上です。大変勉強になりました。
Discussion