要件
- 配列にn個の要素がある
- 条件に合う要素のみ、固めて配列の先頭に移動したい
- 条件に合わない要素の順列は保存する
条件(移動したい値)は複数あるとし、配列で持っていることとする。
結論コード
filter
で条件に合う配列と条件に合わない配列を作ってつなげる。
こちらは非破壊的な方法。
const priority = ['dog', 'cat', 'human']
const target = [
{id:'caw'},
{id:'pig'},
{id:'dog'},
{id:'car'},
{id:'cat'},
{id:'bird'},
{id:'human'},
]
console.log(
target.filter( a => priority.includes(a.id)
).concat(
target.filter( b => !priority.includes(b.id))
)
)
[
{
"id": "dog"
},
{
"id": "cat"
},
{
"id": "human"
},
{
"id": "caw"
},
{
"id": "pig"
},
{
"id": "car"
},
{
"id": "bird"
}
]
sort版
想定していたやりかたができそうになかったので、sort
の自作比較関数で行うことに。
破壊的であることが好きな場合に。
Array.prototype.sort() - JavaScript | MDN
const priority = ['dog', 'cat', 'human']
const target = [
{id:'caw'},
{id:'pig'},
{id:'dog'},
{id:'car'},
{id:'cat'},
{id:'bird'},
{id:'human'},
]
console.log(target.sort((a,b) => {
const abool = priority.includes(a.id)
const bbool = priority.includes(b.id)
if((abool && bbool) || (!abool && !bbool)) {
return 0
}
if (abool) {
return -1
}
return 1
}))
(!abool && !bbool)
のパターンを忘れていて非一致値の順番がめちゃくちゃになったりしたので注意。
filter版の対称性のほうがわかりやすい気もするので意図の汲み取りやすさも含めてお好みで。
(filter
にあるthisArg
がないしsortなのにまったく外部の値を使うのもちょっと不気味なのかもしれない)
当初想定していたやりかた
「条件に合う値だけの配列を削除して返り値にする破壊的関数」を求めたが、調べてもslice
やfind
など複数まとめて取得できなかったりfilter
は非破壊的だったりと一発では行かず。
集めた配列 + あまった配列 で完成させたかったのだが。
map
などで破壊しながら新しい配列を作ってconcat
するぐらいならfilter
を反転してそれぞれ作るほうが綺麗かなと結論コードに。
たいしたコストではないが「あまりものの再利用」ができなかったのが少し不満。