this should be really quick, I have a list of tuples like [("8585", 1);("9232",1);etc] where the second item corresponds to the number of ocurrences the item in "" makes. I was wondering how could i arrange my list from the one that makes more ocurrences to the one that makes least.
f#!
Use sortBy:
let lst = [("8585", 1);("9232",3)]
List.sortBy (fun (_, y) -> -y) lst
Like Gustavo implied, if it's numeric, you can negate it to reverse its order in sorting. That's what the unary operator ~- is for.
Your peculiar choice of data, that is tuples of 'something * int, let me suspect that you are counting the number of certain occurences, and for that Seq.countBy may help (sorry, no list equivalent).
// Your key, Some data
[ "9232", false
"8585", false
"9232", true
"9232", true ]
|> Seq.countBy fst
|> Seq.sortBy (snd >> (~-))
// val it : seq<string * int> = seq [("9232", 3); ("8585", 1)]
That's sorted by the count (snd element of the tuple) of the key (fst element of the tuple) negated.
F# does have List.sortByDescending, so you could have:
[("8585", 1);("9232",3)]
|> List.sortByDescending (fun (_,y) -> y)
Related
Here is the expected input/output:
repeated "Mississippi" == "ips"
repeated [1,2,3,4,2,5,6,7,1] == [1,2]
repeated " " == " "
And here is my code so far:
repeated :: String -> String
repeated "" = ""
repeated x = group $ sort x
I know that the last part of the code doesn't work. I was thinking to sort the list then group it, then I wanted to make a filter on the list of list which are greater than 1, or something like that.
Your code already does half of the job
> group $ sort "Mississippi"
["M","iiii","pp","ssss"]
You said you want to filter out the non-duplicates. Let's define a predicate which identifies the lists having at least two elements:
atLeastTwo :: [a] -> Bool
atLeastTwo (_:_:_) = True
atLeastTwo _ = False
Using this:
> filter atLeastTwo . group $ sort "Mississippi"
["iiii","pp","ssss"]
Good. Now, we need to take only the first element from such lists. Since the lists are non-empty, we can use head safely:
> map head . filter atLeastTwo . group $ sort "Mississippi"
"ips"
Alternatively, we could replace the filter with filter (\xs -> length xs >= 2) but this would be less efficient.
Yet another option is to use a list comprehension
> [ x | (x:_y:_) <- group $ sort "Mississippi" ]
"ips"
This pattern matches on the lists starting with x and having at least another element _y, combining the filter with taking the head.
Okay, good start. One immediate problem is that the specification requires the function to work on lists of numbers, but you define it for strings. The list must be sorted, so its elements must have the typeclass Ord. Therefore, let’s fix the type signature:
repeated :: Ord a => [a] -> [a]
After calling sort and group, you will have a list of lists, [[a]]. Let’s take your idea of using filter. That works. Your predicate should, as you said, check the length of each list in the list, then compare that length to 1.
Filtering a list of lists gives you a subset, which is another list of lists, of type [[a]]. You need to flatten this list. What you want to do is map each entry in the list of lists to one of its elements. For example, the first. There’s a function in the Prelude to do that.
So, you might fill in the following skeleton:
module Repeated (repeated) where
import Data.List (group, sort)
repeated :: Ord a => [a] -> [a]
repeated = map _
. filter (\x -> _)
. group
. sort
I’ve written this in point-free style with the filtering predicate as a lambda expression, but many other ways to write this are equally good. Find one that you like! (For example, you could also write the filter predicate in point-free style, as a composition of two functions: a comparison on the result of length.)
When you try to compile this, the compiler will tell you that there are two typed holes, the _ entries to the right of the equal signs. It will also tell you the type of the holes. The first hole needs a function that takes a list and gives you back a single element. The second hole needs a Boolean expression using x. Fill these in correctly, and your program will work.
Here's some other approaches, to evaluate #chepner's comment on the solution using group $ sort. (Those solutions look simpler, because some of the complexity is hidden in the library routines.)
While it's true that sorting is O(n lg n), ...
It's not just the sorting but especially the group: that uses span, and both of them build and destroy temporary lists. I.e. they do this:
a linear traversal of an unsorted list will require some other data structure to keep track of all possible duplicates, and lookups in each will add to the space complexity at the very least. While carefully chosen data structures could be used to maintain an overall O(n) running time, the constant would probably make the algorithm slower in practice than the O(n lg n) solution, ...
group/span adds considerably to that complexity, so O(n lg n) is not a correct measure.
while greatly complicating the implementation.
The following all traverse the input list just once. Yes they build auxiliary lists. (Probably a Set would give better performance/quicker lookup.) They maybe look more complex, but to compare apples with apples look also at the code for group/span.
repeated2, repeated3, repeated4 :: Ord a => [a] -> [a]
repeated2/inserter2 builds an auxiliary list of pairs [(a, Bool)], in which the Bool is True if the a appears more than once, False if only once so far.
repeated2 xs = sort $ map fst $ filter snd $ foldr inserter2 [] xs
inserter2 :: Ord a => a -> [(a, Bool)] -> [(a, Bool)]
inserter2 x [] = [(x, False)]
inserter2 x (xb#(x', _): xs)
| x == x' = (x', True): xs
| otherwise = xb: inserter2 x xs
repeated3/inserter3 builds an auxiliary list of pairs [(a, Int)], in which the Int counts how many of the a appear. The aux list is sorted anyway, just for the heck of it.
repeated3 xs = map fst $ filter ((> 1).snd) $ foldr inserter3 [] xs
inserter3 :: Ord a => a -> [(a, Int)] -> [(a, Int)]
inserter3 x [] = [(x, 1)]
inserter3 x xss#(xc#(x', c): xs) = case x `compare` x' of
{ LT -> ((x, 1): xss)
; EQ -> ((x', c+1): xs)
; GT -> (xc: inserter3 x xs)
}
repeated4/go4 builds an output list of elements known to repeat. It maintains an intermediate list of elements met once (so far) as it traverses the input list. If it meets a repeat: it adds that element to the output list; deletes it from the intermediate list; filters that element out of the tail of the input list.
repeated4 xs = sort $ go4 [] [] xs
go4 :: Ord a => [a] -> [a] -> [a] -> [a]
go4 repeats _ [] = repeats
go4 repeats onces (x: xs) = case findUpd x onces of
{ (True, oncesU) -> go4 (x: repeats) oncesU (filter (/= x) xs)
; (False, oncesU) -> go4 repeats oncesU xs
}
findUpd :: Ord a => a -> [a] -> (Bool, [a])
findUpd x [] = (False, [x])
findUpd x (x': os) | x == x' = (True, os) -- i.e. x' removed
| otherwise =
let (b, os') = findUpd x os in (b, x': os')
(That last bit of list-fiddling in findUpd is very similar to span.)
I have to write a function in SML/NJ that in a given list, counts successive equal elements and returns a list of pairs (value, count). Function should look like this:
fun group (xs: ''a list): (''a * int) list
I can only use anonymous functions and the structures List, ListPair and Math.
I have no idea how to do it. Can somebody please help me?
A simple but inefficient way is to write this version of group:
val group : ''a list -> ''a list list
and transform the output further into:
val group_count : ''a list -> (''a * int) list
in the following way:
fun group_count xss = map (fn xs => (hd xs, length xs)) xss
But a more efficient way would be to write a function span_count:
fun span_count p x [] count = (count, [])
| span_count p x (y::xs) count =
if p (x, y)
then span_count p x xs (count+1)
else (count, y::xs)
and use it recursively:
fun group_count [] = []
| group_count (x::xs) =
case span_count op= x xs 1 of
(count, ys) => (x, count) :: group_count ys
I have a line of code like this:
list |> List.mapi (fun i x -> y, i)
(Assume that y is already defined type)
But I want to return elements with some condition (e.g filter it)
I am not able to write like this:
list |> List.mapi (fun i x -> if 'condition' then y, i)
because it needs else condition as well and I don't have 'else' case.
I also didn't manage to use filter at the same time, because I need to return correct indexes as well, and if I filter the list, indexes will be changed.
Any ideas?
EDIT
By now, I implemented like this:
list |> List.mapi (fun i a -> if (a = None) then O, i else X, i) |> List.filter (fun (a,i) -> a = O)
I'm giving useless X,i for else case, just to be able to write condition after that and remove X ones. It's working, that's the result I want. But I'm sure there is a better solution.
Let me add yet another answer:
From your question and comments I understand that you want to filter a list by a condition depending on the values while retaining the original indexes.
I'm not sure whether the result should then consist of a list of fixed values and original index or you want to map. The following allows both:
let indexedFilterMap p f =
List.indexed
>> List.filter (snd >> p)
>> List.map (fun (i, x) -> f x, i)
add index
filter by p using second values of indexed list, i.e. original values
map the remaining values and reverse the order in the tuple (s.t. it is value, index)
If you need the index for the mapping (as the question title includes mapi):
let indexedFilterMapi p f =
List.indexed
>> List.filter (snd >> p)
>> List.map f
Or if you need the index for the filter:
let indexedFilteriMap p f =
List.indexed
>> List.filter p
>> List.map (fun (i, x) -> f x, i)
The combination should be straightforward.
These can then be used:
let list = ['a'; 'b'; 'c']
let condition = (<>) 'b'
let y = "fixed value"
indexedFilterMap condition (fun _ -> y) list // [("fixed value", 0); ("fixed value", 2)]
let m (i, _) = sprintf "fixed value %i" i
indexedFilterMapi condition m list // ["fixed value 0"; "fixed value 2"]
let c (i, _) = i <> 1
indexedFilteriMap c (fun _ -> y) list // [("fixed value", 0); ("fixed value", 2)]
If you want to filter, but have indexes applied in strictly monotonically increasing order after filtering, then filter first, and then add the index values:
list |> List.filter condition |> List.mapi (fun i x -> x, i)
Here's an example where b is filtered away from an alphabetical list of characters:
[('a', 0); ('c', 1); ('d', 2); ('e', 3); ('f', 4); ('g', 5); ('h', 6);
('i', 7); ('j', 8); ('k', 9); ('l', 10); ('m', 11); ('n', 12); ('o', 13)]
First of all, be aware that looking up by i from a list is an O(n) operation so if that's what you're doing, there could be a more efficient alternative available by expressing the problem differently.
For the problem as described, you could do something like this:
list
|> List.mapi (fun i x -> x, i)
|> List.choose (fun (x,i) -> if 'condition on x' then Some (y,i) else None)
Returns a list of tuples of y and an element index that satisfied the condition.
Example:
Consider I start with ['a','b','c','d','e'], the first mapi maps the list to [('a',0),('b',1),('c',2),('d',3),('e',4)] then I apply choose with (for example) a condition that select vowels and returns some value y. I end up with [(y,4)].
Edit: In response to your update, here is an example of using this in precisely the way you want.
list
|> List.mapi (fun i x -> x, i)
|> List.choose (fun (x,i) ->
match x with
|O -> Some (O, i)
|X -> None)
There are many ways to achieve this, if you use sequence expressions you don't need to write the else branch:
let list = ['a';'b';'c';'d';'e']
let condition x = x % 2 = 0
[for i = 0 to List.length list - 1 do
if condition i then yield (i, list.[i])]
// val it : (int * char) list = [(0, 'a'); (2, 'c'); (4, 'e')]
But be aware that traversing the list by index is not efficient in a long list. So, it depends what are you looking for, if performance is a must I would use List.fold instead:
list
|> List.fold (fun (i, acc) e -> (i + 1, if condition i then (i, e)::acc else acc)) (0, [])
|> snd
|> List.rev // if you care about the order
I need to sort a list that is type
ListToSort val: (string*Seq<string>) list
My idea is to sort this list by the length of the sequence
Im using the commands List.Sortby snd and Seq.Length but I havent been able to make it work..
Any ideas?
thanks
EDIT:
A more Clear idea of the code is (the list that I want to sort is created by Seq.grouby that groups repeated elements in the original list)
let grouped =
OriginalList
|> Seq.groupBy (fun value -> if value = value then value else "else" )
|> Seq.toList
|> Seq.Sortby.... // sort the list by the length of the sequence
Adding the line
|> List.sortBy(fun (_, s) -> Seq.length s) –
Suggusted by vcsjones made it work
let grouped =
OriginalList
|> Seq.groupBy (fun value -> if value = value then value else "else" )
|> Seq.toList
|> List.sortBy(fun (_, s) -> Seq.length s) –
This returned the list sorted!!
How can I remove the duplicate from a list in Erlang?
Suppose I have a list like:
[1,1,2,3,4,5,5,6]
How can I get:
[1,2,3,4,5,6]
You could use sets, for example:
my_nonDuplicate_list1() ->
List = [1,1,2,3,4,5,5,6],
Set = sets:from_list(List),
sets:to_list(Set).
This returns [1,2,3,4,5], no more duplicates, but most likely not sorted.
Another possibility without the usage of sets would be:
my_nonDuplicate_list2() ->
List = [1,1,2,3,4,5,5,6],
lists:usort(List).
In this case it returns [1,2,3,4,5], no more duplicates and sorted.
And for those looking to preserve the order of the list:
remove_dups([]) -> [];
remove_dups([H|T]) -> [H | [X || X <- remove_dups(T), X /= H]].
A possible solution that will Preserve the order of the elements to help you learn how to manipulate lists, would involve two functions:
delete_all(Item, [Item | Rest_of_list]) ->
delete_all(Item, Rest_of_list);
delete_all(Item, [Another_item| Rest_of_list]) ->
[Another_item | delete_all(Item, Rest_of_list)];
delete_all(_, []) -> [].
remove_duplicates(List)-> removing(List,[]).
removing([],This) -> lists:reverse(This);
removing([A|Tail],Acc) ->
removing(delete_all(A,Tail),[A|Acc]).
To test,
Eshell V5.9 (abort with ^G)
1> mymod:remove_duplicates([1,2,3,1,2,4,1,2,1]).
[1,2,3,4]
2>
I would do something like this at first to preserve order, though it is not recommended. Remember that AddedStuff ++ Accumulator is OK but Accumulator ++ AddedStuff is really bad.
rm_dup(List) ->
lists:foldl(
fun(Elem, Acc) ->
case lists:member(Elem, Acc) of
true ->
Acc;
false ->
Acc ++ [Elem]
end
end, [], List
).
This solution is much more efficient if you want to preserve order:
rm_dup(List) ->
lists:reverse(lists:foldl(
fun(Elem, Acc) ->
case lists:member(Elem, Acc) of
true ->
Acc;
false ->
[Elem] ++ Acc
end
end, [], List
)).
for my opinion, the best option is to use lists:usort()
But in case you don't want to use BIF's, and you want the list to be sorted, I suggest a version of quick sort, in this implementation you will get the list sorted without duplicate values.
unique_sort([]) -> [];
unique_sort([Pivot|T]) ->
unique_sort ([X || X <- T, X < Pivot ) ]++
[Pivot] ++
unique_sort ([X || X <- T, X > Pivot ]).
Module sets has two functions that can be composed and do the job in an efficient way: sets:from_list/1 returns a set with all the elements of a list (with no duplicated elements from definition) and sets:to_list/1 returns a list with the elements of a set. Here is an example of use:
4> sets:to_list(sets:from_list([1,1,2,3,4,5,5,6])).
[3,6,2,5,1,4]
We could define the function as
nub(L) -> sets:to_list(sets:from_list(L)).