How can I remove nils from this list ,lets say i get:
[{"some","other",[]},nil,{{"more","somemore",[]},nil,nil}]
In the end I would like to extract only the first elements from the long tuples and put them on a list,
Something like:
["some", "more"]
You can remove nils from the list using function like that:
filter_out_nils(Data) when is_list(Data) ->
Pred = fun(Element) -> Element /= nil end,
lists:filter(Pred, Data).
This function does not remove nils within tuples though.
And you can use a couple of functions to extract every first non tuple element in you list (like strings "some" and more):
extract_first_elements(Data) when is_list(Data) ->
lists:map(fun extract_first_non_tuple_element/1, Data).
extract_first_non_tuple_element({})-> {};
extract_first_non_tuple_element(Data) when is_tuple(Data)->
case element(1, Data) of
First when is_tuple(First) -> extract_first_non_tuple_element(First);
Other -> Other
end.
Function extract_first_non_tuple_element is recursive, because in your example tuple can be nested.
So to test this functions:
Data1 = [{"some","other",[]}, nil, {{"more","somemore",[]}, nil, nil}].
filter_out_nils(Data1).
[{"some","other",[]},{{"more","somemore",[]},nil,nil}] % resulting list without nils
Data2 = extract_first_elements(Data1).
["some","more"] % extracted first elements
Update.
To remove nils from nested tuples we can use function like that:
filter_out_nils_from_tuple(Data) when is_tuple(Data) ->
TList = tuple_to_list(Data),
Fun = fun(Element, Acc) ->
case Element of
nil -> Acc;
Tuple when is_tuple(Tuple) -> Acc ++ [filter_out_nils_from_tuple(Tuple)];
Other -> Acc ++ [Other]
end
end,
Result = lists:foldl(Fun, [], TList),
list_to_tuple(Result).
Filtering out nils and getting the first element of nested tuples in your example can be achieved with a single recursive function, with a clause for the nil case:
f([Item | T], Acc) when is_tuple(Item) -> f([element(1, Item) | T], Acc);
f([nil | T], Acc) -> f(T, Acc); % filter out nil
f([Other | T], Acc) -> f(T, [Other | Acc]);
f([], Acc) -> lists:reverse(Acc).
Since you added erlang-shell tag, please note this solution will not work directly in the shell. Indeed, recursive functions in the shell shall be written as functions taking a function (themselves) as an argument (cf: How do you write a fun that's recursive in Erlang?).
F = fun(F, [Item | T], Acc) when is_tuple(Item) ->
F(F, [element(1, Item) | T], Acc);
(F, [nil | T], Acc) -> F(F, T, Acc);
(F, [Other | T], Acc) -> F(F, T, [Other | Acc]);
(_F, [], Acc) -> lists:reverse(Acc)
end.
F(F, List, []).
Please also note that this solution has specific behaviors for cases not covered in your question:
It will crash with a function clause error if the input list contains an empty tuple. Yet, this might be a desired behavior. Otherwise, you can simply add a new function clause to handle it as desired (should empty tuples be filtered out or returned?).
It will accept and return non-tuple elements in the list (except nil), e.g. f(["some", "more"], []). To avoid this, you would need a slightly different logic.
It will crash if the argument is not a proper list.
Related
I'm trying to self-learn some programming in a functional programming language and recently stumbled on the problem of generating all the permutations of length m from a list of length n, with repetition. Mathematically, this should result in a total of n^m possible permutations, because each of the m 'slots' can be filled with any of the n elements. The code I have currently, however, does not give me all the elements:
let rec permuts n list =
match n, list with
0, _ -> [[]]
| _, [] -> []
| n, h :: t -> (List.map (fun tt -> h::tt) (permuts (n-1) list))
# permuts n t;;
The algorithm basically takes one element out of a list with m elements, slaps it onto the front of all the combinations with the rest of the elements, and concatenates the results into one list, giving only n C m results.
For example, the output for permuts 2 [1;2;3] yields
[[1;1]; [1;2]; [1;3]; [2;2]; [2;3]; [3;3]]
whereas I actually want
[[1;1]; [1;2]; [1;3]; [2;1]; [2;2]; [2;3]; [3;1]; [3;2]; [3;3]]
-- a total of 9 elements. How do I fix my code so that I get the result I need? Any guidance is appreciated.
Your error appears on the second line of:
| n, h :: t -> List.map (fun tt -> h::tt) (permuts (n-1) list)
# permuts n t
Indeed, with this you are decomposing the set of n-tuples with k elements as the sum of
the set of (n-1)-tuples prefixed with the first element
the set of n-tuples with (k-1) elements
Looking at the cardinal of the three sets, there is an obvious mismatch since
k^n ≠k^(n-1) + (k-1)^n
And the problem is that the second term doesn't fit.
To avoid this issue, it is probably better to write a couple of helper function.
I would suggest to write the following three helper functions:
val distribute: 'a list -> 'a list -> 'a list list
(** distribute [x_1;...;x_n] y returns [x_1::y;...x_n::y] *)
val distribute_on_all: 'a list -> 'a list list
(** distribute_on_all x [l_1;...;l_n] returns distribute x l_1 # ... # distribute x l_n *)
val repeat: int -> ('a -> 'a) -> 'a -> 'a
(** repeat n f x is f(...(f x)...) with f applied n times *)
then your function will be simply
let power n l = repeat n (distribute_on_all l) [[]]
In Haskell, it's very natural to do this using a list comprehension:
samples :: Int -> [a] -> [[a]]
samples 0 _ = [[]]
samples n xs =
[ p : ps
| p <- xs
, ps <- samples (n - 1) xs
]
It seems to me you never want to recurse on the tail of the list, since all your selections are from the whole list.
The Haskell code of #dfeuer looks right. Note that it never deconstructs the list xs. It just recurses on n.
You should be able to copy the Haskell code using List.map in place of the first two lines of the list comprehension, and a recursive call with (n - 1) in place of the next line.
Here's how I would write it in OCaml:
let perm src =
let rec extend remaining_count tails =
match remaining_count with
| 0 -> tails
| _ ->
(* Put an element 'src_elt' taken from all the possible elements 'src'
in front of each possible tail 'tail' taken from 'tails',
resulting in 'new_tails'. The elements of 'new_tails' are one
item longer than the elements of 'tails'. *)
let new_tails =
List.fold_left (fun new_tails src_elt ->
List.fold_left (fun new_tails tail ->
(src_elt :: tail) :: new_tails
) new_tails tails
) [] src
in
extend (remaining_count - 1) new_tails
in
extend (List.length src) [[]]
The List.fold_left calls may look a bit intimidating but they work well. So it's a good idea to practice using List.fold_left. Similarly, Hashtbl.fold is also common and idiomatic, and you'd use it to collect the keys and values of a hash table.
The motivating problem is: Code a lazy list whose elements are all possible combinations of 0 and 1 i.e. [0], [1], [0;0], [0;1], etc..
Working in OCaml, I've written auxiliary functions for generating the list of permutations of length n+1 given n and for converting a list into a lazy list. The problem comes from the final function in the below block of code:
type 'a seq =
| Nil
| Cons of 'a * (unit -> 'a seq)
let rec adder = function
| [] -> []
| [[]] -> [[0];[1]]
| xs::ys -> (0::xs)::(1::xs)::(adder ys)
let rec listtoseq = function
| [] -> Nil
| xs::ys -> Cons(xs, fun () -> listtoseq ys)
let rec appendq xq yq =
match xq with
| Nil -> yq
| Cons (x, xf) -> Cons (x, fun() -> appendq (xf ()) yq)
let genlist xs = appendq (listtoseq xs) (genlist (adder xs))
Calling genlist [[0];[1]] results in a stack overflow. The issue seems to be that since genlist is an infinite loop I want to delay evaluation, yet evaluation is needed for appendq to work.
If this were a problem where one element is added to the lazy list at a time I could solve it, but I think the difficulty is that each set of length n permutations must be added at a time, and thus I don't know any other solution besides using an append function.
One way to look at your problem is that appendq isn't lazy enough. You can make things work if you define a function appendqf with this type:
'a seq -> (unit -> 'a seq) -> 'a seq
In other words, the second parameter isn't a sequence. It's a function that returns a sequence.
(Note that this type, unit -> 'a seq, is what actually appears inside a Cons.)
I tried this and it works for me.
My custom datatype is defined as follows: datatype 'a mylist = NIL | CONS of 'a * 'a mylist;
Been trying for hours but can't figure out how to reverse such a list.
My code that doesn't work:
fun reverse NIL = NIL
| reverse (CONS(head,tail)) = reverse tail # [head];
Here is the function call:
reverse (CONS(4,CONS(3,CONS(2,NIL))));
Use of the append operator will increase the time complexity of this solution. I would instead use a helper function in order to perform a tail-recursive call whereby the list is reversed in a stack-like manner.
e.g.
fun reverse xs =
let
fun revhelp NIL ys = ys
| revhelp (CONS(x,xs)) ys = revhelp xs (CONS(x,ys))
in
revhelp xs NIL
end;
You can't use the builtin append (#) and lists ([head]) with your own list type.
You need CONS (head, NIL) instead of [head], and you need to write your own
append: 'a mylist -> 'a mylist -> 'a mylist
or
append: ('a mylist * 'a mylist) -> 'a mylist
Implementing append left as an exercise.
I'm trying to implement a function used to split a list into two equal-length halves (the problem assumes the list is of even length) in F#. Using the search function yielded a thread that deals with the exact same problem I'm trying to work through now:
Split list into two equal lists in F#
I'm trying to implement the solution given by the user Juliet, who provides a partial answer:
let cut l =
let rec cut = function
| xs, ([] | [_]) -> xs
| [], _ -> []
| x::xs, y::y'::ys -> cut (xs, ys)
cut (l, l)
Which returns the second half of the list. I'm trying to work out a way to return the first half, so I made some modifications:
let rec cut(xs, ys) =
let zs = []
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
x::zs
cut (xs, ys)
You can probably tell that F# is my first functional programming language, and I'm kinda confused as to how it works, exactly. Pattern-matching is a new thing for me, and I was never very good at recursion to start with.
From what I understand, the way pattern matching works is that it's basically a more versatile version of an if-then-else statement, where the code to the left of the -> is the conditional (the "if" bit), and everything to the right is the block of code to execute if the conditional check passes (the "then" bit).
What I'm not totally sure of is whether you're allowed to do things like this:
| x::xs, y1::y2::ys ->
x::zs
cut (xs, ys)
If pattern matching really does work like if statements, then it should be, since in an if statement it would look something like
if (x::xs && y1::y2::ys)
{
x::zs
cut (xs, ys)
}
Anyhow, it doesn't seem like the statement x::zs is allowed, since Visual Studio gives me a warning:
The result of this expression is implicitly ignored. Consider using "ignore" to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. let result = expr'.
I'm not sure what it means by that last part. I thought I had already declared the list as a local variable of the function in the line
let zs = []
All I'm trying to do is take the head of the list xs in each recursive iteration of the cut function and add it to another list zs, which when the base case is reached, would contain every element x passed over (in other words, the first half of the list), then return both xs (which contains the second half of the list) and the list containing the first half, but it doesn't seem like that's allowed?
Anyhow, it doesn't seem like the statement x::zs is allowed, since Visual Studio gives me a warning.
The expression x::zs is allowed, but Visual Studio is trying to tell you that it has no effect. x::zs creates a new list but then immediately discards it (it does not mutate the existing value!).
Based on the rest of the code provided, zs should contain the first half of the list, but zs will only ever contain the empty list [] because that's the only value it is assigned to. In a language like C#, you would simply mutate the list by appending to it but in F# you shouldn't do that. Since you're already using recursion, this is a sign that zs should be a parameter to your recursive function so that you can use the new value later. (I've found that some people understand recursion better if they think of it as a callback. When you recurse, it's like providing parameters to a callback function. Any values you want to accumulate during the recursion process need to be provided as parameters to your function.)
Putting this all together, I think what you want is something like this:
let rec cut(xs, ys, zs) =
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
cut (xs, ys, x::zs)
Typically, you'd hide this function inside a non-recursive function which sets up your arguments correctly:
let cut(xs, ys) =
let rec impl(xs, ys, zs) =
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
impl (xs, ys, x::zs)
impl(xs, ys, [])
Note: There's no need to use ,s to seperate arguments in F#. When you do this, you are actually declaring that a function has a single argument consisting of a tuple. This is not usually what you want and it prevents currying the function. All you need to use to separate arguments is whitespace:
let cut xs ys =
let rec impl xs ys zs =
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
impl xs ys (x::zs)
impl xs ys []
Here's a way to do it by adding another accumulator value that builds up the slow items into a list:
let cut l =
let rec loop acc rem =
match rem with
| xs, ([] | [_]) -> List.rev acc, xs
| [], _ -> [], []
| x::xs, y::y'::ys -> loop (x::acc) (xs, ys)
loop [] (l, l)
> cut [1;2;3;4;5;6]
([1; 2; 3], [4; 5; 6])
So I have this function which seems to be non-tail-call friendly, right?
let rec insertFooInProperPosition (foo: Foo) (bar: list<Foo>): list<Foo> =
match bar with
| [] -> [ foo ]
| head::tail ->
if (foo.Compare(head)) then
foo::bar
else
head::(insertFooInProperPosition foo tail)
Then I try to figure out how to use an accumulator so that the last thing done by the function is call itself, and I come up with this:
let rec insertFooInProperPositionTailRec (foo: Foo) (headListAcc: list<Foo>) (bar: list<Foo>): list<Foo> =
match bar with
| [] -> List.concat [headListAcc;[ foo ]]
| head::tail ->
if (foo.Compare(head)) then
List.concat [headListAcc; foo::bar]
else
insertFooInProperPosition foo (List.concat [headListAcc;[head]]) tail
let rec insertFooInProperPosition (foo: Foo) (bar: list<Foo>): list<Foo> =
insertFooInProperPositionTailRec foo [] bar
However, as far as I understand, the usage of List.concat would make this function much less efficient, right? So then how would I go and do this conversion properly?
Your solution looks ok if using recursion is required. However, the this task can be achieved without recursion (and a bit faster).
To concatenate two lists the first list should be copied and its last element should point to the first element of the second list. This is O(N) where N is the size of the first list. Growing list at the tail requires multiple concatenations, resulting traversing list for each N, which makes the complexity quadratic (hope I right here).
Instead of recursive approach that adds items to the list, the faster approach would be probably to find the insertion index and then copy all the items before it in one go and then concat it with new item and the rest of the list. This requires only three passes through the list so O(N).
let insertFooInProperPosition (foo : Foo) (bar : Foo list) : Foo list =
bar
|> List.tryFindIndex (fun v -> v.Compare foo)
|> function | None -> List.append bar [ foo ]
| Some i -> let before, after = List.splitAt i bar
List.concat [ before; [ foo ]; after ]
Unfortunately you cannot build up an F# list from head to tail (unless you use functions internal to the F# Core library that use mutation under the hood). Therefore the best idea is probably to build up a new list from the old one, prepending the next elements as we go, and inserting foo at the right point. At the end, the new list is reversed to obtain the same order as the old list:
let insertFoo (foo : Foo) bar =
let rec loop acc = function
| [] -> prep (foo :: acc) []
| x :: xs ->
if foo.Compare x
then prep (x :: foo :: acc) xs
else loop (x :: acc) xs
and prep acc = function
| [] -> acc
| x :: xs -> prep (x :: acc) xs
loop [] bar |> List.rev
I guess #knocte was quicker with an equivalent solution…
#AlexAtNet's solution doesn't look bad, but if you still want recursive, you can avoid so much concat calls this way:
let rec insertFooInProperPositionTailRec (foo: Foo)
(headListAcc: list<Foo>)
(bar: list<Foo>)
: list<Foo> =
match bar with
| [] -> List.rev (foo::headListAcc)
| head::tail ->
if (foo.Compare(head)) then
let newAcc = List.rev headListAcc
[ yield! newAcc
yield! foo::bar ]
else
let newAcc = head::headListAcc
insertFooInProperPositionTailRec foo newAcc tail
let rec insertFooInProperPosition (foo: Foo) (bar: list<Foo>): list<Foo> =
insertFooInProperPositionTailRec foo [] bar
Not sure if it's more performant than #AlexAtNet's, mmm...