fallen mcmullan
fallen mcmullan

Reputation: 75

Check list inside list for equal amount and empty space

I tried to make a list inside a list. Where i check if there is the same amount of numbers, inside each list, and return bool true/false. I am not sure i did it right, and it also needs to check if each lists is empty and return true or false. i cant wrap my head around it. thanks ahead! can i make this code more simple and how do i check if empty and return bool true or false?

  let lis1 = [[ 1; 2; 3; ] ; [ 4; 5; 6; ]]

    let isTable (lis1 : 'a list list) = 
        let mutable tabellen = false
        let item0 = lis1.Item 0
        for i = 0 to (lis1.Length)-1 do 
            if item0.Length = (lis1.Item i).Length then 
                tabellen <- true
            else
                tabellen <-false
        tabellen

    printfn"%b" (isTable lis1)

Upvotes: 1

Views: 104

Answers (2)

dumetrulo
dumetrulo

Reputation: 1991

You can make @ChadGilbert's answer into a one-liner (if you don't mind it being slightly long):

let isTable l = 1 = l |> List.map List.length |> List.distinct |> List.length

Short and sweet, you can see immediately what is going on, but not as efficient as possible because it iterates the list twice. Just in case you would like a slightly more efficient solution, I came up with the following:

let isTable = function
    | [] -> true
    | h :: t ->
        List.length t = 0 ||
        List.forall (fun l -> List.length h = List.length l) t

This checks first if the list is empty (and I defined that case to be a table but feel free to return false there instead), and if not, it works on the tail. If it is empty, the list has a single element and is thus trivially a table; otherwise, check that all lists have the same length as the first one.

Upvotes: 0

Chad Gilbert
Chad Gilbert

Reputation: 36375

In F#, it is usually better to start with functional and immutable data types unless you absolutely need to mutate something.

You can map over the list to get the length of each inner list like this:

List.map List.length lis1
// yields: [3; 3]

You can then take the distinct items from that list via List.distinct:

List.map List.length lis1 |> List.distinct
// yields: [3]

You can pattern match on the length of that list, and based on your logic, you can determine whether a list of lists is a table by whether it has a single item in our resulting list.

let isTable list =
    match List.map List.length list |> List.distinct |> List.length with
    | 1 -> true
    | _ -> false

Examples:

printfn "%A" <| isTable [[ 1; 2; 3; ] ; [ 4; 5; 6; ]]
// yields: true

printfn "%A" <| isTable [[ 1; 2; ] ; [ 3; 4; 5; 6; ]]
// yields: false

printfn "%A" <| isTable []
// yields: false

Upvotes: 1

Related Questions