React で名前の配列を4個ごとに区切ったサブリストをつくり、 それをテーブルのそれぞれ行として扱う必要が生じた。
リストを n 個ごとに分割する その3で 書いたコードを TypeScript に移植したので、その覚え書きです。
2025-07-09 update 結論だけ知りたい場合はこちらをご覧ください: リストを n 個ごとに分割する ファイナルアンサー
その3で書いたコードそのままです。
// main.kts
typealias TypeT = String
typealias TypeR = List<List<String>>
val toSubListList: (List<String>, Int)->TypeR = { list, n->
val initial: TypeR = listOf(listOf())
val operation: (TypeR, TypeT)->TypeR = { acc, itemValue->
if( acc.isEmpty() ){
val newSubList = listOf(itemValue)
acc + listOf(newSubList)
} else {
val lastSubList = acc.last()
if( lastSubList.size < n ){
val newSubList = lastSubList + listOf(itemValue)
acc.take( acc.size-1 ) + listOf(newSubList)
} else {
val newSubList = listOf(itemValue)
acc + listOf(newSubList)
}
}
}
list.fold(initial, operation)
}
val list = listOf("1","2","3","4","5","6","7","8")
println(toSubListList(list, 2)) // [[1, 2], [3, 4], [5, 6], [7, 8]]
println(toSubListList(list, 3)) // [[1, 2, 3], [4, 5, 6], [7, 8]]
println(toSubListList(list, 4)) // [[1, 2, 3, 4], [5, 6, 7, 8]]
println(toSubListList(list, 5)) // [[1, 2, 3, 4, 5], [6, 7, 8]]
これを TypeScript に書き直します。
TypeScript を実行するのに 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 でそれを使う方法がすぐにわからなかったので、 代わりに lodash を使うことにします。
次のようにすることで使えました。
$ deno add npm:lodash
Add npm:lodash@4.17.21
main.ts を次のように書いて動作確認:
import _ from 'lodash'
const sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0)
console.log(sum)
$ deno run main.ts
$ deno main.ts
としても普通に実行できた。
それではこれで toSubListList 関数を書いていこう。
単に移植しただけで特別なことは何もしていない。
// main.ts
import _ from 'lodash'
const toSubListList = (list: string[], n: number) => {
const isEmpty = (listList: string[][]): boolean => {
return (listList.length===0)
}
const take = (listList: string[][], n: number): string[][] => {
if (isEmpty(listList)) {
return []
} else {
return listList.slice(0, n)
}
}
const initialValue: string[][] = []
return _.reduce(list, (acc: string[][], item: string)=> {
if (isEmpty(acc)) {
const newSubList = [item]
return acc.concat([newSubList])
} else {
const lastSubList: string[] = _.last(acc)
if (lastSubList.length < n) {
const newSubList = lastSubList.concat([item])
return take(acc, acc.length-1).concat([newSubList])
} else {
const newSubList = [item]
return acc.concat([newSubList])
}
}
}, initialValue)
}
const list = ["1","2","3","4","5","6","7","8"]
console.log( toSubListList(list, 2) )
console.log( toSubListList(list, 3) )
console.log( toSubListList(list, 4) )
console.log( toSubListList(list, 5) )
$ deno main.ts
[ [ "1", "2" ], [ "3", "4" ], [ "5", "6" ], [ "7", "8" ] ]
[ [ "1", "2", "3" ], [ "4", "5", "6" ], [ "7", "8" ] ]
[ [ "1", "2", "3", "4" ], [ "5", "6", "7", "8" ] ]
[ [ "1", "2", "3", "4", "5" ], [ "6", "7", "8" ] ]
このままでは 要素が string のサブリストしか作成できなくて 不都合だったので、ジェネリックにしました。 T と書いただけです。
import _ from 'lodash'
//function toSubListList<T>(list: T[], n: number){
const toSubListList = <T>(list: T[], n: number): T[][] => {
const isEmpty = (listList: T[][]): boolean => {
return (listList.length===0)
}
const take = (listList: T[][], n: number): T[][] => {
if (isEmpty(listList)) {
return []
} else {
return listList.slice(0, n)
}
}
const initialValue: T[][] = []
return _.reduce(list, (acc: T[][], item: T)=> {
if (isEmpty(acc)) {
const newSubList = [item]
return acc.concat([newSubList])
} else {
const lastSubList = _.last(acc)
if (lastSubList.length < n) {
//if (lastSubList!==undefined && lastSubList.length < n) {
const newSubList = lastSubList.concat([item])
return take(acc, acc.length-1).concat([newSubList])
} else {
const newSubList = [item]
return acc.concat([newSubList])
}
}
}, initialValue)
}
const list = ["1","2","3","4","5","6","7","8"]
console.log( toSubListList(list, 2) )
console.log( toSubListList(list, 3) )
console.log( toSubListList(list, 4) )
console.log( toSubListList(list, 5) )
これでリストの要素の型が string 以外でもサブリストにできます。
時間ができたら具体的な例を書きます。 それから lodash ではなく underscore.js を使った場合も書く予定。
かきかけです。