LINUX.ORG.RU

[F#][оптимизация] each with each

 


0

2

Как можно оптимизировать по времени работы:

let c = [1..1000]

let eachWithEachAndCoollect f l =
        let _, result =  l |> List.fold 
                                (fun (acc, result) el ->
                                    let extended =
                                        acc |> List.fold 
                                                (fun acc2 ael -> 
                                                    match f el ael with
                                                    | Some(t) -> t :: acc2
                                                    | None -> acc2) 
                                                [] 
                                    (el :: acc), result @ extended)
                                ([],[])
        result
        
let eachWithEachAndCoollect2 f l =
    let rec iter l acc =
        match l with
        | h :: t ->
             iter t acc @ (t |> List.choose (fun el -> f h el))
        | [] -> acc
    iter l []
                    
c |> eachWithEachAndCoollect (fun a b -> Some(a,b))
(*Real: 00:00:33.223, CPU: 00:00:31.109, GC gen0: 470, gen1: 233, gen2: 28*)

c |> eachWithEachAndCoollect2 (fun a b -> Some(a,b))
(*Real: 00:00:32.130, CPU: 00:00:32.015, GC gen0: 482, gen1: 288, gen2: 20*)

к примеру:

let eachWithEachAndCoollect3 f l =
    let res = System.Collections.ArrayList()
    let rec iter l =
        match l with
        | h :: t ->
            t |> List.iter 
                    (fun el ->
                        match f h el with
                        | Some(a) -> 
                            res.Add(a) 
                            ()
                        | None -> ()) 
            iter t
        | [] -> 0
    iter l
    res.ToArray() |> Array.toList

c |> eachWithEachAndCoollect3 (fun a b -> Some(a,b))
(*Real: 00:00:00.473, CPU: 00:00:00.453, GC gen0: 4, gen1: 1, gen2: 0*)

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от pseudo-cat

только результатом будет список obj. Я сделал костыль, но видимо это не очень хорошо и главное интересует можно ли такую ф-цию использовать с разными реальными типами 'b одновременно или могут возникнуть проблемы?

костыль -

let eachWithEachAndCoollect4 (f : 'a -> 'a -> 'b option) l =
    let res = System.Collections.ArrayList()
    let rec iter l =
        match l with
        | h :: t ->
            t |> List.iter 
                    (fun el ->
                        match f h el with
                        | Some(a) -> 
                            ignore (res.Add(a)) 
                        | None -> ()) 
            iter t
        | [] -> 0
    ignore (iter l)
    res.ToArray() |> Array.toList |> List.map (fun el -> el :?> 'b)    

pseudo-cat ★★★
() автор топика

Переписать в процедурном стиле.

note173 ★★★★★
()

У тебя вообще какая задача? Ты только на множестве целых чисел функцию строишь или предполагается любой числовой тип в с?

delete83 ★★
()
Ответ на: комментарий от delete83

Если ты ее на множестве всех упорядоченных типов решаешь, то вообще вряд ли удастся что-то оптимизировать, хотя в F# я ноль и не могу всех тонкостей знать.

delete83 ★★
()
Ответ на: комментарий от delete83

на множестве всех типов, какая разница какой тип если есть ф-ция сравнения?

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от pseudo-cat

Честно говоря, я не понял тебя. Этот List<_> (он же, ResizeArray<_> в F#) по производительности чуточку лучше, чем ArrayList.

dave ★★★★★
()
Ответ на: комментарий от anonymous

без пандорического захвата работать не будет.

buddhist ★★★★★
()
let eachWithEachAndCoollect4 f l =
    let rec iter l acc =
        match l with
        | h :: t ->
             iter t ((t |> List.choose (fun el -> f h el)) :: acc)
        | [] -> acc
    seq {
        for lst in iter l [] do
            for e in lst -> e } |> List.ofSeq

let r = c |> eachWithEachAndCoollect4 (fun a b -> Some(a,b));;

Real: 00:00:00.363, CPU: 00:00:00.358, GC gen0: 8, gen1: 4, gen2: 0

val r : (int * int) list = [(999, 1000); (998, 999); (998, 1000); (997, 998); (997, 999); (997, 1000); (996, 997); (996, 998); (996, 999); (996, 1000); (995, 996); (995, 997); (995, 998); (995, 999); (995, 1000); (994, 995); (994, 996); (994, 997); (994, 998); (994, 999); (994, 1000); (993, 994); (993, 995); (993, 996); (993, 997); (993, 998); (993, 999); (993, 1000); (992, 993); (992, 994); (992, 995); (992, 996); (992, 997); (992, 998); (992, 999); (992, 1000); (991, 992); (991, 993); (991, 994); (991, 995); (991, 996); (991, 997); (991, 998); (991, 999); (991, 1000); (990, 991); (990, 992); (990, 993); (990, 994); (990, 995); (990, 996); (990, 997); (990, 998); (990, 999); (990, 1000); (989, 990); (989, 991); (989, 992); (989, 993); (989, 994); (989, 995); (989, 996); (989, 997); (989, 998); (989, 999); (989, 1000); (988, 989); (988, 990); (988, 991); (988, 992); (988, 993); (988, 994); (988, 995); (988, 996); (988, 997); (988, 998); (988, 999); (988, 1000); (987, 988); (987, 989); (987, 990); (987, 991); (987, 992); (987, 993); (987, 994); (987, 995); (987, 996); (987, 997); (987, 998); (987, 999); (987, 1000); (986, 987); (986, 988); (986, 989); (986, 990); (986, 991); (986, 992); (986, 993); (986, 994); (986, 995); ...]

Никогда не используй @ если нужна скорость.

Norgat ★★★★★
()
Ответ на: комментарий от Norgat

Чуть изменил,

let eachWithEachAndCoollect4 f l =
    let rec iter l acc =
        match l with
        | h :: t ->
            let a = 
                List.fold (fun acc e ->
                                (f h e) :: acc) acc t
            iter t a
        | [] -> acc
    iter l []

c |> eachWithEachAndCoollect4 (fun a b -> Some(a,b));;

Real: 00:00:00.149, CPU: 00:00:00.156, GC gen0: 5, gen1: 2, gen2: 1

Norgat ★★★★★
()
Ответ на: комментарий от Norgat

ок, вариант хорош, но только мне надо так -

let eachWithEachAndCoollect4 f l =
    let rec iter l acc =
        match l with
        | h :: t ->
            let a = 
                List.fold (fun acc e ->
                               match (f h e) with
                               | Some(res) -> res :: acc
                               | None -> acc) 
                          acc t
            iter t a
        | [] -> acc
    iter l []

pseudo-cat ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.