Распутность в коллекции - PullRequest
0 голосов
/ 19 ноября 2018

Оригинальный вопрос

Я хочу использовать F #, чтобы найти близость согласных к гласным в наборе слов.Так, например, в слове «верх» T - это (-1: 1) от гласного, а P - (1: 1) от гласного.

Первое число в паре - это позиция, а второе -число - это число раз, которое оно находится в этой позиции относительно ближайшего гласного.

В «согласных» C - (-1: 1), N - (1: 3), (-2: 1), (-1, 1), S - (2: 1), (-1: 1), (3: 1) и T - (2: 1).

Я подозреваю, что должениспользуйте комбинацию groupBy, findIndex и countBy.

type ConsonantPos = { Name: string
                      BeforeVowel: int
                      AfterVowel: int }

let isVowel (x:string) =
    List.contains x ["a";"e"; "i"; "o"; "u"]

let consonantPosVsVowel x lst = 
      let rec getConsonanatPos x beforeVowel afterVowel currentPos lst = 
          match lst with
            | [] -> {Name = x; BeforeVowel = beforeVowel; AfterVowel = afterVowel}
            | h::t -> 
              if isVowel h then
                {Name = x; BeforeVowel = beforeVowel; AfterVowel = afterVowel}
              else 
                getConsonanatPos  x (beforeVowel - 1) (afterVowel + 1) (currentPos + 1) t

      getConsonanatPos x 0 0 0 lst


["b"; "a"; "c"] |> consonantPosVsVowel "b"
// val it : ConsonantPos = {Name = "b"; BeforeVowel = -1; AfterVowel = 1;}
["b"; "c"; "d"; "e"; "f"; "g"] |> consonantPosVsVowel "b"
// val it : ConsonantPos = {Name = "b"; BeforeVowel = -3; AfterVowel = 3;}

Пересмотренное решение

По состоянию на 21/11/2018 оба предложения работали и хорошо работали для решения проблемы, как я изначально указал.

Конечно, этот вопрос был только частью программы, которую я писал.Поскольку я расширил программу и изучил данные, BEEP , один ответ оказался проще для повторного использования: это тот, который я пометил как ответ.

Моя проблема, как оказалосьбыло мое непонимание и неспособность использовать коллекции.

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Вот немного другой подход, который по-разному разбивает задачу.

  • Сопоставьте элемент с его хвостом (отрицательное расстояние, вперед) и головками (положительный, отсталый). Это делается с помощью рекурсивной функции и двух аккумуляторы
  • Отфильтровать полученный список для элементов, не являющихся гласными
  • Сопоставьте его с парами параметров, представляющих отрицательные и положительные расстояния, с другая рекурсивная функция, и собрать эти пары в плоский список снова при транспонировании их значений
  • Сгруппируйте этот список по элементам и сопоставьте результат с кортежем расстояния и числа вхождений

let genTail2 xss =
    let rec aux accl accr = function
    | [] -> List.rev accr
    | x::xs -> aux (x::accl) ((x, (xs, accl))::accr) xs
    aux [] [] xss
// val genTail2 : xss:'a list -> ('a * ('a list * 'a list)) list

let dist2 pred (x, (ls, rs)) =
    let rec aux n i = function
    | [] -> None
    | y::ys -> if pred y then Some(x, n) else aux (n + i) i ys
    aux -1 -1 ls, aux 1 1 rs
// val dist2 :
//   pred:('a -> bool) ->
//     x:'b * ('a list * 'a list) -> ('b * int) option * ('b * int) option

let tuple2List = function
| None, None -> []
| Some x, None | None, Some x -> [x]
| Some x, Some y -> [y; x]
// val tuple2List : 'a option * 'a option -> 'a list

let isVowel = ResizeArray['a';'e';'i';'o';'u'].Contains
// val isVowel : (char -> bool)    

"consonants"
|> fun s -> s.ToLower()
|> Seq.toList
|> genTail2
|> List.filter (fst >> isVowel >> not)
|> List.collect (dist2 isVowel >> tuple2List)
|> Seq.groupBy fst
|> Seq.map (fun (x, xs) -> x, Seq.countBy snd xs)
|> Seq.iter (printfn "%A")
0 голосов
/ 19 ноября 2018

Попробуйте это:

let isVowel (x:char) =
    List.contains x ['a';'e'; 'i'; 'o'; 'u']

let countConsonants (word:string) =
    let vowelsp, consonants =
        word
        |> Seq.mapi(fun i c-> c,i )
        |> Seq.toArray
        |> Array.partition (fst >> isVowel)
    let vowels = vowelsp |> Array.map snd
    consonants
    |> Seq.collect (fun (c,i) -> 
        match vowels |> Array.tryFindIndex ((<) i) with
        | None   -> [ vowels.Length - 1 ]
        | Some j -> [ j - 1     ; j     ]
        |> Seq.choose (fun j -> 
            if j < 0 then None else
            Some(c, i - vowels.[j])
        )
    )
    |> Seq.countBy id
    |> Seq.map (fun ((l,p), c) -> (l,(p, c)) )
    |> Seq.groupBy fst
    |> Seq.map (fun (l, s) -> l, s |> Seq.map snd |> Seq.toArray)
    |> Seq.toArray

"consonants"
|> countConsonants
|> Seq.iter (printfn "%A")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...