Сопоставить другую функцию с первым и последним элементом в списке - PullRequest
3 голосов
/ 03 октября 2011

У меня есть функция, в которой я хочу преобразовать список с плавающей точкой в ​​другой, где для каждого элемента я хочу, чтобы х процентов элемента i перетекли в элемент i + 1

пример:

let p3 = [0.1; 0.2; 0.4; 0.2; 0.1]

тогда p3_s должно быть:

[0.05; 0.15; 0.3; 0.3; 0.2]

. Для этого я взял половину каждого элемента и добавил его к следующему элементу.

  • 0.1 стал 0,05потому что он дал 0,05 следующему, предыдущий элемент отсутствует
  • 0,2 стал 0,15, потому что он дал 0,1 следующему и получил 0,05 от первого
  • и т.д.
  • и, наконец,0,1 стал 0,2, потому что это 0,01 от предыдущего.Там нет следующего элемента.

Теперь я пришел с этим, который работает, но только для списка размером 5:

// create list
let p3 = [0.1; 0.2; 0.4; 0.2; 0.1]

let shiftList orgList shift =    

    // chop list up in tuples of what stays and what moves
    let ms = orgList |> List.map (fun p-> (p * shift, p * (1.0-shift))) 

    // map new list 
    ms |> List.mapi (fun i (move, stay) -> 
        match i with 
        | 0 -> stay
        | 4 -> stay + fst ms.[i-1] + move // note hardcoded 4
        | _ -> stay + fst ms.[i-1])

// get shifted list
shiftList p3 0.5

Теперь по вопросам:

1) Как мнесделать так, чтобы это совпадало с любым списком длины?Теперь я жестко закодировал 4 в выражении совпадения, но я бы хотел принять любой список длины.

Я пробовал это:

let shiftList orgList shift =    

    // chop list up in tuples of what stays and what moves
    let ms = orgList |> List.map (fun p-> (p * shift, p * (1.0-shift))) 

    // find length 
    let last = orgList.Length - 1

    // map new list 
    ms |> List.mapi (fun i (move, stay) -> 
        match i with 
        | 0     -> stay
        | last  -> stay + fst ms.[i-1] + move 
        | _     -> stay + fst ms.[i-1]) // now this one will never be matched

Но это не будет трактовать last как число 4, вместо этого оно станет переменной для i, даже если last уже объявлено выше.

Итак, как мне сопоставить переменную, чтобы я мог по-разному относиться к последнему элементу?Найти первый легко, потому что он в 0.

2) Как бы вы это сделали?Я все еще довольно новичок в F #, о многих вещах, о которых я еще не знаю.Угадайте общий случай: как мне сопоставить другую функцию с первым и последним элементом списка, а общую функцию с другими?

Заранее спасибо,

Gert-Jan

Ответы [ 5 ]

5 голосов
/ 03 октября 2011

Вот более функциональное решение

let func (input:float list) =
    let rec middle_end input_ =
        match input_ with
        |h::t::[] -> ((h/2.0)+t)::[]
        |h::t::tt ->((h+t)/2.0)::(middle_end (t::tt))
        | _ -> [] //fix short lists
    let fst = input.Head/2.0
    fst::middle_end(input)

Кроме того, для этого требуется только один проход по списку, а не 3 в решении Рамона, а также меньшее временное хранилище.

2 голосов
/ 03 октября 2011

В качестве альтернативы написанию собственной рекурсивной функции вы также можете использовать встроенные функции.Проблема может быть решена довольно легко с помощью Seq.windowed.Вам все еще нужен специальный случай для последнего элемента:

let p3 = [0.1; 0.2; 0.4; 0.2; 0.1] 

// Prefix zero before the list, pre-calculate the length
let p3' = (0.0 :: p3)
let l = p3.Length

// Perform the transformation
p3' 
|> Seq.windowed 2
|> Seq.mapi (fun i ar -> 
    (if i = l - 1 then ar.[1] else ar.[1] / 2.0) + ar.[0] / 2.0)
|> List.ofSeq
1 голос
/ 04 октября 2011

Просто еще одна идея,

let bleh p3 =
    match Seq.fold (fun (give,acc) i -> i*0.5,((i*0.5 + give) :: acc)) (0.0,[]) p3 with
    |(give,h::t) -> give+h :: t |> List.rev
    |(_,[]) -> []
1 голос
/ 03 октября 2011

Использование List.scan:

let lst = [0.1; 0.2; 0.4; 0.2; 0.1]
let len = (lst.Length-1)

lst 
|> List.mapi (fun i e -> (i,e)) 
|> List.scan (fun (c,_) (i,e) -> if i = len then (0.0,e+c) else ((e/2.0),(e/2.0)+c)) (0.0,0.0) |> List.tail 
|> List.map snd
1 голос
/ 03 октября 2011

Вы хотите сделать:

let shiftList orgList shift =    

    // chop list up in tuples of what stays and what moves
    let ms = orgList |> List.map (fun p-> (p * shift, p * (1.0-shift))) 

    // find length 
    let last = orgList.Length - 1

    // map new list 
    ms |> List.mapi (fun i (move, stay) -> 
        match i with 
        | 0     -> stay
        | last' when last' = last -> stay + fst ms.[i-1] + move 
        | _     -> stay + fst ms.[i-1]) // now this one will never be matched
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...