Avoiding loops in F #

I have a list of strings and numbers like

let stringsAndNums = [("aa-",20); ("b1",20); ("aa",10); ("b12",10); ("+aa-",30)]

I need to break the list into groups of strings that are included one in the other.

For each of the above groups, I need to find the minimum and maximum value.

This is what I tried to do: it works, but I don’t think it is idiomatic F #, and I think I should avoid for loops.

for tup in stringsAndNums do
    let subject, value = tup
    let related = 
        stringsAndNums |> List.filter( 
            fun o -> 
                       let osubject, ovalue = o; 
                       osubject.Contains(subject) || subject.Contains(osubject);
             )

    let relvalues = related |> List.map(fun o -> 
                                  let osubject, ovalue = o; 
                                  ovalue
                       )  
    let min = (relvalues |> List.min)
    let max = (relvalues |> List.max) 
    printfn "%A" (subject, value, min, max, (max - min))

Also, how can I define a function that returns a list of set results, instead of printing them?

The required conclusion.

The results I get look great

("aa-", 20, 10, 30, 20)
("b1", 20, 10, 20, 10)
("aa", 10, 10, 30, 20)
("b12", 10, 10, 20, 10)
("+aa-", 30, 10, 30, 20)

In fact, two groups in this case are formed from

  • +aa-with a value of 30, aawith a value of 10, aa-with a value of 20, therefore max is 30 and min is 10
  • b1with a value of 20, b12with a value of 10

My decision

: for-loop, ?

let results =
   stringsAndNums |> List.map(fun tup ->

//for tup in stringsAndNums do
    let subject, value = tup
    let related = 
        stringsAndNums |> List.filter( 
            fun o -> 
                       let osubject, ovalue = o; 
                       osubject.Contains(subject) || subject.Contains(osubject);
             )
    //for reltup in related do
    let relvalues = related |> List.map(fun o -> 
                                  let osubject, ovalue = o; 
                                  ovalue
                       )  
    let min = (relvalues |> List.min)
    let max = (relvalues |> List.max) 
    printfn "%A" (subject, value, min, max, (max - min))
)

for result in results do
    printf "%A" result
+4
2

, ,

let stringsAndNums = [("aa-",20); ("b1",20); ("aa",10); ("b12",10); ("+aa-",30)]
let results =
    let split (subject, value) = 
        let related =
            //first I created a named function for the filter expression
            let filtering (osubject:string, _) = osubject.Contains(subject) || subject.Contains(osubject) 
            stringsAndNums |> List.filter filtering 
        //accessing the 2 first items of a tuple can be done via fst, snd 
        let relvalues = related |> List.map snd 
        let min = (relvalues |> List.min)
        let max = (relvalues |> List.max) 
        //I assume you wanted to return that tuple so away with the printf
        (subject, value, min, max, (max - min))

    stringsAndNums |> List.map split

for result in results do
    //and lastly use printfn (n-for newline) so the printing is nicer
    printfn "%A" result
+4

.

let subjectValues = [("aa-",20); ("b1",20); ("aa",10); ("b12",10); ("+aa-",30)]

let getRelated (subject, value) =
    let relValues = 
        subjectValues
        |> List.choose (fun (s, v) ->
            if s.Contains(subject) || subject.Contains(s)
            then Some v
            else None)

    let min = relValues |> List.min
    let max = relValues |> List.max

    (subject, value, min, max, (max - min))

let results = subjectValues |> List.map getRelated

printfn "%A" results
  • List.map unit (- void). .

  • , let.

  • , , List.map, , .

  • List.map ... List.filter List.choose, . let.

  • , , .

+6

Source: https://habr.com/ru/post/1658176/


All Articles