JavaScript で...というか TypeScript で 配列の要素をひっくり返す には list.reverse() すればよいだけなのだが、この方法では元の配列もひっくり返る(破壊される)らしい。 list.toReversed() を使えば問題ないらしい。
reverse を使う:
const list0 = [1,2,3,4,5]
const list1 = list0.reverse()
console.log(list1) // [ 5, 4, 3, 2, 1 ] ひっくり返った
console.log(list0) // [ 5, 4, 3, 2, 1 ] ひっくり返った!! (この挙動は受け入れ難い)
toReversed を使う:
const list1 = list0.toReversed()
console.log(list1) // [ 5, 4, 3, 2, 1 ] ひっくり返った
console.log(list0) // [ 1, 2, 3, 4, 5 ] 元のまま
deno を使います。
$ deno --version
deno 2.4.1 (stable, release, x86_64-unknown-linux-gnu)
v8 13.7.152.6-rusty
typescript 5.8.3
underscore js を使えるようにする:
$ deno add npm:underscore
foldl を使ってひっくり返す:
// main.ts
import { foldl } from 'underscore'
const list0: number[] = [1,2,3,4,5]
const list1: number[] = foldl(list0, (acc: number[], item: number): number[] => {
return [item].concat(acc)
}, [] as number[])
console.log(list1) // [ 5, 4, 3, 2, 1 ]
console.log(list0) // [ 1, 2, 3, 4, 5 ] 元のまま
実行する:
$ deno run main.ts
[ 5, 4, 3, 2, 1 ]
[ 1, 2, 3, 4, 5 ]
型を明示して書いた方が書くときはわかりやすいがコードを読むときは冗長すぎでうっとうしい。
型を省略して簡潔に書けば次のとおり:
import { foldl } from 'underscore'
const list0 = [1,2,3,4,5]
const list1 = foldl(list0, (acc, item) => [item].concat(acc), [])
console.log(list1) // [ 5, 4, 3, 2, 1 ]
console.log(list0) // [ 1, 2, 3, 4, 5 ] 元のまま
結局左から順に折り畳み( foldl )つつ新しい配列を生成していくのだが、そのとき現在対象となっている item を(生成する配列の)先頭に配置していくだけの話。
右から畳むとさらに簡単にかけるのでついでに試した。
import { foldr } from 'underscore'
const list0 = [1,2,3,4,5]
const list1 = foldr(list0, (acc, item) => acc.concat([item]), [])
console.log(list1) // [ 5, 4, 3, 2, 1 ]
console.log(list0) // [ 1, 2, 3, 4, 5 ] 元のまま
今度は右から折り畳むので acc.concat([item]) としている。つまり foldl とは逆に対象となる item を生成する配列の末尾に追加していく。
foldl 版の reverse を Haskell に移植:
list0 :: [Int]
list0 = [1,2,3,4,5]
list1 :: [Int]
list1 = reverse' list0
f :: [Int] -> Int -> [Int]
f acc item = item : acc
reverse' :: [Int] -> [Int]
reverse' xs = foldl f [] xs
main :: IO ()
main = putStrLn $ show list1
環境はこれ:
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.4.7
実行:
$ runghc main.hs
[5,4,3,2,1]
以上です。