リストの連続する数字を連続範囲に統合する


論文の書き方が狂いそうです.来て口ぶりを変える
先ほどクイズチャンネルの問題を見ました.
javascript配列差分値配列
bjqincyは書いています
配列
[1,2,3,6,9,20,21,34,45,67,68]
次と前の差を返します.
連続差分値が1に等しい場合、最初の要素と最後の出力を行います.
結果
テーブルとして表示
効果を表示:
1-3
6,
9,
20---21
34
45
67-66
この前提は入力された配列が厳密に昇順されなければなりません.要素が重複してはいけません.さもなくば私の下のコードはすべて駄目になりました.
厳格な昇順ではないなら、foldの時に判断を加えなければなりません.
F〓〓を使うならば、きわめて簡単です.一度積み重ねるだけでいいです.XD
F├1.6.16で作ります.
let merge l = List.foldBack (fun e acc ->
  match acc with
  | x :: xs ->
    match x with
    | [a] -> if a - 1 = e then [e; a] :: xs else [e] :: acc
    | [a; b] -> if a - 1 = e then [e; b] :: xs else [e] :: acc
  | _ -> [e] :: acc) l []

printfn "%A" (merge [1; 2; 3; 6; 9; 20; 21; 34; 45; 67; 68])
表示:
[[1; 3]; [6]; [9]; [20; 21]; [34]; [45]; [67; 68]]
(変なものです.関数名がmergToRangesであれば、関数全体を括弧で包んでください.mやmergeのような短い名前で大丈夫です.これはどうしたものですか?メールで理由を聞いて、返事を待っています.)
同じロジックをJavaScriptと書いてもいいです.しかし、F铉のバージョンの効率がいいと思います.F钻の表はチェーンであり、JavaScriptの配列は……配列です.
function foldRight(func, ary, acc) {
    if (0 == ary.length) return acc
    return func(ary[0], foldRight(func, ary.slice(1), acc))
}

function mergeToRanges(ary) {
    return foldRight(function(e, acc) {
        if (0 == acc.length)
            return [[e]].concat(acc)
        if (1 == acc[0].length && acc[0][0] - 1 == e)
            return [[e, acc[0][0]]].concat(acc.slice(1))
        if (2 == acc[0].length && acc[0][0] - 1 == e)
            return [[e, acc[0][1]]].concat(acc.slice(1))
        else
            return [[e]].concat(acc)
    }, ary, [])
}

print(mergeToRanges([1,2,3,6,9,20,21,34,45,67,68]).join('
'))
表示:
1,3
6
9
20,21
34
45
67,68
(print()はRhinoの内建関数です.ブラウザで試すならalert()で代用します.)
まあ、JavaScriptと書いたらちょっとおかしいです.XDです.
実は普通の考えでJavaScriptで書くのも簡単ですか?
私はF〓版でList.fold BackではなくList.foldで作成したリストの順序を維持するために元の表の順序と一致します.チェーンの特徴は、F〓の表を後ろから前に作らないといけないので、fold Backになります.
しかし、JavaScriptの配列は配列であり、前から後ろへ、または後ろから前への構造は大丈夫です.その実用的なfoldはJavaScriptにとってもっと直観的かもしれません.foldをさらにループに変換すると、次のようになります.
function mergeToRanges(ary) {
    var acc = null
    var last = null
    for (var i = 0; i < ary.length; i++) {
        var e = ary[i]
        if (!acc) {
            last = [e]
            acc = [last]
        } else if (1 == last.length && last[0] + 1 == e) {
            last = [last[0], e]
            acc[acc.length-1] = last
        } else if (2 == last.length && last[1] + 1 == e) {
            last = [last[0], e]
            acc[acc.length-1] = last
        } else {
            last = [e]
            acc = acc.concat(last)
        }
    }
    return acc
}

mergeToRanges([1,2,3,6,9,20,21,34,45,67,68]).join('
')
出力は問題とは違っていますが、切り替えが便利なので、書かないようにします.
もちろん、この方法の効率は理想的ではありません.特にアラy.co ncatを繰り返し呼び出します.改善しますか?あとでもう一度言ってください.暇がないです.
引き続き潜って私のものを叩いてTvTに行きます.