I have a string[] list and I wish to group the 5th element in the string array of all the list..
I found two different ways in doing this
let rec Publication x y (z:string [] list) =
if x < z.Length then
let muro = [z.[x].[y]]
let rest = Publication (x+1) y z
List.append muro rest
else []
where z is the string[] list and y is the element that I wish to list.
and
let Publication x (z:string [] list) = [for i in 0 .. (z.Length-1) -> z.[i].[x]]
In the first case, I get a stack overflow error when working with a large set of data and the second one takes to long. Can anyone help me find a third and more eficient way? thanks!
Your second version seems sensible on the surface, but I wonder if the problem is not the indexed access to z, as the list is iterated from the head for each z.[i] call. What I would try is plain and simple:
let publication idx (lst: string [] list) =
lst |> List.map (fun arr -> arr.[idx])
You have a list of arrays and an index, you go through the list and get element by the index from each array.
Related
Can someone tell me the formal reason why list/arrays and such are considered more secure when it comes to incremental steps i.e (List.fold > loops).
Exampel code in F#
Functional way (list)
let rec sum lst =
match lst with
| [] -> 0
| x::xs -> x + sum xs
Imperative way (incremental)
let sum n m =
let mutable s = 0
for i=n to m do
s <- s + i
s
If by security you mean "safer" -- then I think this will explain it some. To begin with if you're summing a list, a fold should be somewhat safer as it removes the need for the programmer to correctly index the list:
let sum lst =
let mutable s = 0
for i=0 to (List.length lst - 1) do
s <- s + lst.[i]
s
You avoid a lot of pitfalls completely by using the library function:
let sum lst =
let folder acc element =
acc + element
List.fold folder 0 lst
The fold handles all the edge cases for you, in terms of indices, and list length. (note: this could also be done with a List.reduce (+) lst however that does not handle an empty list, where as a fold does).
The short of it all is that it keeps the programmer from making mistakes on silly index math, and keeps the focus on the actual logic of what is being done.
EDIT: I ironically messed up the index logic in my initial post
In SML, how can i count the number of appearences of chars in a String using recursion?
Output should be in the form of (char,#AppearenceOfChar).
What i managed to do is
fun frequency(x) = if x = [] then [] else [(hd x,1)]#frequency(tl x)
which will return tupels of the form (char,1). I can too eliminate duplicates in this list, so what i fail to do now is to write a function like
fun count(s:string,l: (char,int) list)
which 'iterates' trough the string incrementing the particular tupel component. How can i do this recursively? Sorry for noob question but i am new to functional programming but i hope the question is at least understandable :)
I'd break the problem into two: Increasing the frequency of a single character, and iterating over the characters in a string and inserting each of them. Increasing the frequency depends on whether you have already seen the character before.
fun increaseFrequency (c, []) = [(c, 1)]
| increaseFrequency (c, ((c1, count)::freqs)) =
if c = c1
then (c1, count+1)
else (c1,count)::increaseFrequency (c, freqs)
This provides a function with the following type declaration:
val increaseFrequency = fn : ''a * (''a * int) list -> (''a * int) list
So given a character and a list of frequencies, it returns an updated list of frequencies where either the character has been inserted with frequency 1, or its existing frequency has been increased by 1, by performing a linear search through each tuple until either the right one is found or the end of the list is met. All other character frequencies are preserved.
The simplest way to iterate over the characters in a string is to explode it into a list of characters and insert each character into an accumulating list of frequencies that starts with the empty list:
fun frequencies s =
let fun freq [] freqs = freqs
| freq (c::cs) freqs = freq cs (increaseFrequency (c, freqs))
in freq (explode s) [] end
But this isn't a very efficient way to iterate a string one character at a time. Alternatively, you can visit each character by indexing without converting to a list:
fun foldrs f e s =
let val len = size s
fun loop i e' = if i = len
then e'
else loop (i+1) (f (String.sub (s, i), e'))
in loop 0 e end
fun frequencies s = foldrs increaseFrequency [] s
You might also consider using a more efficient representation of sets than lists to reduce the linear-time insertions.
I have a list like List = ["google","facebook","instagram"] and a string P1 = "https://www.google.co.in/webhp?pws=0&gl=us&gws_rd=cr".
Now I need to find which element of List is present inside the P1.
For this I implemented below recursive function, but it returns ok as final value, is there a way that when (in this case) google is found, then H is returned and terminate the other recursive calls in stack.
I want this function to return google.
traverse_list([],P1)-> ok;
traverse_list([H|T],P1) ->
Pos=string:str(P1,H),
if Pos > 1 ->
io:fwrite("Bool inside no match is ~p~n",[Pos]),
io:fwrite("inside bool nomathc, ~p~n",[H]),
H;
true->
io:fwrite("value found :: ~p~n",[Pos])
end,
traverse_list(T,P1).
It returns ok because the stop condition of your recursion loop does it:
traverse_list([],P1)-> ok;
For this you should use lists:filter/2 or a list comprehension:
List = ["google","facebook","instagram"],
P1 = "https://www.google.co.in/webhp?pws=0&gl=us&gws_rd=cr",
lists:filter(fun(X) -> string:str(P1,X) > 1 end,List),
% or
[X || X <- List, string:str(P1,X) > 1],
I'm trying to build a function which takes as input two list of type
(string*string) list
and returns one list of the same type. The first list is like a "lookup" list in which the second element is the element to search and the first element is the element to use for the substitution. The aim of the function is to find which element in the second list is equal to which element of the first list. In case of matching the element of the second list will be substitute with the correspondent element of the tuple in the first element. Below an example:
fun check([("0","s0"),("1","s0l0s1"),("2","s1"),("3","s1l1s0")],[("s0","s0l0s1"),("s0l0s1","s1"),("s1","s1l1s0"),("s1l1s0","s0")]);
With these inputs the function should return:
val it = [("0","1"),("1","2"),("2","3"),("3","0")]
Since "s0" corresponds to "0", "s0l0s1" corresponds to "1", "s1" corresponds to "2" and "s1l1s0" corresponds to "3".
I've done two functions so far:
fun check1((l1 as (x1,y1))::nil,(l2 as (x2,y2))::nil) = if x2 = y1 then [(x1,y2)] else nil
|check1((l1 as (x1,y1))::rest1,(l2 as (x2,y2))::rest2) =
if x2 = y1 then (x1,y2)::check1(rest1,rest2)
else check1(rest1,l2::rest2)
fun check2((l1 as (x1,y1))::nil,(l2 as (x2,y2))::nil) = if y2 = y1 then [(x2,x1)] else nil
|check2((l1 as (x1,y1))::rest1,(l2 as (x2,y2))::rest2) =
if y2 = y1 then (x2,x1)::check2(rest1,rest2)
else check2(rest1,l2::rest2)
The first one checks the element of the first tuple of the second list and the second function checks the element of the second tuple. But they don't work properly. Someone can help me in understanding where is the mistake?
Thanks a lot!
You're making this way too complicated.
This first function looks up a string in the first list:
fun lookup ((a,b)::xs) v = if v = b then a else lookup xs v
| lookup nil v = v;
And this one just runs recursively on both elements in the second list:
fun check (xs,((a,b)::ys)) = (lookup xs a, lookup xs b)::check(xs,ys)
| check (xs,nil) = nil;
First of all im VERY VERY noob in f# so I need your help :)
I have a library with 50 lists that each have around 10 entries
What I need to do is join all 50 lists into one big list. The things is that I cant use "for" or mutable variables.
what I have done (which I think is horribly done) is:
let rec finalList x =
if x < wallID.Length then List.append [interfaz.hola(wallID.Item(x)).[0].[1]] [finalList]
else listaFinal (x+1)
printfn "list %A" (listaFinal 10 )
WallID represents one of the 50 lists and interfaz.GetMuroHumano(wallID.Item(x)).[0].[1] gets me one of the entries that I need. (for now if a can just get one of the data for each wallID im ok)
again im verrrrry noob and I hope you guys can help me
thanks
EDIT:
So now its partially working..
let rec finalList x y =
if x < wallID.Length then
if y < [interfaz.GetMuroHumano(wallID.Item(x)).[y]].Length then
let current = [interfaz.GetMuroHumano(wallID.Item(x)).[y].[1]]
let rest = finalList (x y+1)
List.append current rest
else finalList (x+1 y)
else []
vut im getting errors calling the function finalList it says that "y" is not an int but a string
It is hard to say what is wrong with your code without seeing a complete version. As Daniel points out, there is a built-in library function for doing that - in fact, you do not even need List.collect, because there is List.concat that takes a list of lists.
However, you might still try to get your original code to work - this is useful for understanding functional concepts! I added some comments that can help you understand how it should work:
let rec finalList x =
if x < wallIDLength then
// Get the list at the index 'x'
let current = interfaz.GetMuroHumano(wallID.Item(x))
// Recursively process the rest of the lists
let rest = finalList (x + 1)
// Check that both 'current' and 'rest' are variables
// of type list<'T> where 'T is the element type
List.append current rest
else
// Return empty list if we got too far
[]
// Start from the first index: 0
printfn "list %A" (finalList 0)
let flatten xs = List.collect id xs