список подмассивов массива - PullRequest
0 голосов
/ 16 сентября 2018

Я пытаюсь реализовать функцию stride n a, где n - длина шага, а a - массив.При вызове типа stride 2 [| "a"; "b"; "c"; "d" |] он должен вернуть что-то вроде [ [|"a"; "b"|]; [|"c"; "d" |] ].Я новичок в F # и ничего не знаю об использовании массивов на функциональном языке.Я знаю, что я написал, что это мусор, но это начало:

let stride n (a : array 'a) =
    let rec r ind =
        if ind >= a.length()
        then
            []
        else 
            a[ind .. (ind + n - 1)]::r(ind + n)
    in
    r 0

(см. Также по dotnetfiddle ).Это не компилируется.Я добавил параметр типа array 'a, потому что компилятору не удалось найти метод length, но этот параметр типа не разрешен.

В контексте я пытаюсь получить группы буквиз строки, поэтому я планирую назвать это как stride 2 myString.ToCharArray().

1 Ответ

0 голосов
/ 16 сентября 2018

Прежде всего, для этого уже есть приложение - оно называется Array.chunkBySize:

> Array.chunkBySize 2 [|1;2;3;4;5;6;7|]
val it : int [] [] = [|[|1; 2|]; [|3; 4|]; [|5; 6|]; [|7|]|]

И в Seq и List есть аналогичные функциимодуля, так что если ваша цель - работать со строками, я бы рассмотрел вариант Seq, поскольку string уже реализует интерфейс seq:

> Seq.chunkBySize 2 "abcdefg";;
val it : seq<char []> =
  seq [[|'a'; 'b'|]; [|'c'; 'd'|]; [|'e'; 'f'|]; [|'g'|]]

Но если вы 'Если вы заинтересованы в образовании, а не в GSD, то вот оно:

Логика кода прекрасна, за исключением того, что у вас есть несколько чисто синтаксических ошибок и одна логическая.

Первый , тип "массив из" не обозначен array 'a.В общем случае обозначение F # для универсальных типов имеет вид T<'a> или 'a T, например list<int> или int list.Однако это не работает для массивов, потому что массивы особенные.Существует тип System.Array, но он не является общим, поэтому его нельзя использовать таким образом.Вместо этого идея массива как бы встраивается в CLR, поэтому вы должны использовать специальный синтаксис: 'a[].

Итак: a : 'a[] вместо a : array 'a

Second , хотя у массива есть свойство length, оно пишется с заглавной буквы (т. Е. Length) и это свойство, а не метод, поэтому после него не должно быть скобок.

Итак: a.Length вместо a.length()

Однако это не совсем F # способ.Методы и свойства - лучше, функции - лучше.Путь F # заключается в использовании функции Array.length.

Итак: Array.length a вместо a.length()

Бонус: если вы это сделаете, нет необходимости в аннотации типа: 'a[], потому что компилятор теперь может выяснить это по типу Array.length.

Третий , для индексации массивов, списков и всего остального, имеющего индекс, требуетсяточка перед открывающей скобкой.

Итак: a.[ind .. (ind + n - 1)] вместо a[ind .. (ind + n - 1)]

Четвертый , in не является необходимым в F #.Вы можете просто опустить его.

С вышеуказанными модификациями ваша программа будет работать.Но только для массивов, длина которых кратна n.На всех остальных вы получите IndexOutOfRangeException.Это потому, что у вас также есть ...

Логическая ошибка в том, что когда вы проверяете, что ind находится в пределах массива, вы не проверяете, что ind + n - 1как хорошо.Итак, вам нужен третий случай в вашей ветке:

if ind >= Array.length a then
    []
elif ind + n - 1 >= Array.length a then
    a.[ind..] :: r (ind+n)
else
    a.[ind .. (ind+n-1)] :: r (ind+n)

Теперь все готово для прайм-тайма.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...