How to shuffle a List in Elm? - elm

Let's say I have a list containing the numbers 1 through 5. How would I write a function in Elm called shuffleList such that it takes a list of integers as an argument and returns a randomized version of the list?
E.g.,
shuffleList [1,2,3,4,5]
{-5,1,2,4,3-}
It is OK to hardcode the random seed

You probably want the shuffle function from elm-community/random-extra. Example of using that on Ellie
If you want to do this by hand though, given an initial Seed you can do the following (this makes use of some functions from the elm-community/list-extra package)
import List.Extra exposing (getAt, removeAt)
import Random exposing (Seed, int, step)
shuffleList : Seed -> List a -> List a
shuffleList seed list =
shuffleListHelper seed list []
shuffleListHelper : Seed -> List a -> List a -> List a
shuffleListHelper seed source result =
if List.isEmpty source then
result
else
let
indexGenerator =
int 0 ((List.length source) - 1)
( index, nextSeed ) =
step indexGenerator seed
valAtIndex =
getAt index source
sourceWithoutIndex =
removeAt index source
in
case valAtIndex of
Just val ->
shuffleListHelper nextSeed sourceWithoutIndex (val :: result)
Nothing ->
Debug.crash "generated an index outside list"
An example using this on Ellie

http://package.elm-lang.org/packages/elm-community/elm-random-extra/1.0.2 has Random.Array.shuffle so just convert to an array, shuffle, and convert back

Related

difference between two lists that include duplicates

I have a problem with two lists which contain duplicates
a = [1,1,2,3,4,4]
b = [1,2,3,4]
I would like to be able to extract the differences between the two lists ie.
c = [1,4]
but if I do c = a-b I get c =[]
It should be trivial but I can't find out :(
I tried also to parse the biggest list and remove items from it when I find them in the smallest list but I can't update lists on the fly, it does not work either
has anyone got an idea ?
thanks
You see an empty c as a result, because removing e.g. 1 removes all elements that are equal 1.
groovy:000> [1,1,1,1,1,2] - 1
===> [2]
What you need instead is to remove each occurrence of specific value separately. For that, you can use Groovy's Collection.removeElement(n) that removes a single element that matches the value. You can do it in a regular for-loop manner, or you can use another Groovy's collection method, e.g. inject to reduce a copy of a by removing each occurrence separately.
def c = b.inject([*a]) { acc, val -> acc.removeElement(val); acc }
assert c == [1,4]
Keep in mind, that inject method receives a copy of the a list (expression [*a] creates a new list from the a list elements.) Otherwise, acc.removeElement() would modify an existing a list. The inject method is an equivalent of a popular reduce or fold operation. Each iteration from this example could be visualized as:
--inject starts--
acc = [1,1,2,3,4,4]; val = 1; acc.removeElement(1) -> return [1,2,3,4,4]
acc = [1,2,3,4,4]; val = 2; acc.removeElement(2) -> return [1,3,4,4]
acc = [1,3,4,4]; val = 3; acc.removeElement(3) -> return [1,4,4]
acc = [1,4,4]; val = 4; acc.removeElement(4) -> return [1,4]
-- inject ends -->
PS: Kudos to almighty tim_yates who recommended improvements to that answer. Thanks, Tim!
the most readable that comes to my mind is:
a = [1,1,2,3,4,4]
b = [1,2,3,4]
c = a.clone()
b.each {c.removeElement(it)}
if you use this frequently you could add a method to the List metaClass:
List.metaClass.removeElements = { values -> values.each { delegate.removeElement(it) } }
a = [1,1,2,3,4,4]
b = [1,2,3,4]
c = a.clone()
c.removeElements(b)

Best way to get next element of a List in Elm

I am currently trying to figure out the best way of traversing a List.
What do I mean by traversing?
Example:
I have a List of Users:
userList : List User
userList =
[user, user, user, user]
and I have a currentUser, which must be a user out of the userList
So what I want to achieve is:
I want to have something like List.getNext which takes the userList and the current user and returns the next user in the list, relative to the currentUser
Here is my implementation. I think it is very complicated - so has anyone an idea how to do this in a better style?
traverseList : List a -> a -> Maybe (Maybe a)
traverseList list currentElement =
let
indexList =
List.indexedMap
(\index element ->
if element == currentElement then
index
else
-1
)
list
currentAsIndex =
let
mayBeIndex =
List.maximum indexList
in
case mayBeIndex of
Just index ->
index
Nothing ->
0
getWanted =
List.map
(\( id, element ) ->
if id == (currentAsIndex + 1) then
Just element
else
Nothing
)
(List.indexedMap (,) list)
|> List.filter
(\element ->
element /= Nothing
)
|> List.head
in
getWanted
Explanation:
My approach is to get the list, make an index list of the given list (looks like this [-1, -1, -1, 3, -1, -1])
Then I get the maximum of this list - as this gives me the position of the current user in a List.indexedMap.
Then I iterate the original as an List.indexedMap and figure out the next one (in our case No. 4) and return that element. Else I return nothing.
Then I filter this List of Nothings and just one user and extract the user from the list by using List.head.
The Result is a Maybe (Maybe user)... that is not so nice... or?
Thanks for any ideas to do something like this in a better functional way.
I really try to get better in functional programming..
Here is a pretty naive, recursive solution:
getWanted : List a -> a -> Maybe a
getWanted list currentElement =
let findNextInList l = case l of
[] -> Nothing
x :: [] -> if x == currentElement
then List.head list
else Nothing
x :: y :: rest -> if x == currentElement
then Just y
else findNextInList (y :: rest)
in
findNextInList list
The idea here is look at the first two elements of the list, and if the first is the current element, take the second. If not, try again with the tail of the list.
Corner cases must be handled (you can write at least 4 unit tests for this function):
current element not found at all
current element is the last in the list
the list might be empty
Maybe there is a more elegant solution, but recursion is a pretty common technique in functional programming, so I wanted to share this approach.
If you are willing to import list-extra you can use
import List.Extra as LE exposing ((!!))
getNext : a -> List a -> Maybe a
getNext item list =
list
|> LE.elemIndex item
|> Maybe.map ((+) 1)
|> Maybe.andThen ((!!) list)
If the found element is the last in the list it returns Nothing
Another possible solution:
getNext : List a -> a -> Maybe a
getNext list element =
list
|> List.drop 1
|> zip list
|> List.filter (\(current, next) -> current == element)
|> List.map (\(current, next) -> next)
|> List.head
zip : List a -> List b -> List (a,b)
zip = List.map2 (,)
We drop the first element of the list and then zip it with the original list to get a list of tuples. Each element of the tuple contains the current element and the next element. We then filter that list, take the 'next' element from the tuple and take the head of the final list.
I like farmio's library-based approach best, and is what I'll be using in future.
That said, for being new to elm and not looking over its libraries, my erstwhile approach has been as in the following: i.e. index the list, find index if any of searched-for item, get item at next index if any.
nextUser : List User -> User -> Maybe User
nextUser lst usr =
let
numberedUsers =
List.map2 (\idx u -> ( idx, u )) (List.range 1 (List.length lst)) lst
usrIdx =
List.filter (\( idx, u ) -> u.name == usr.name) numberedUsers
|> List.head
|> Maybe.map Tuple.first
|> Maybe.withDefault -1
in
List.filter (\( idx, u ) -> idx == usrIdx + 1) numberedUsers
|> List.head
|> Maybe.map Tuple.second
Another way with as much fiddlery would be to use folds.
Maybe instead of List just use Array, which provides index-based access.
There are some good answers to the concrete question. I'd like to suggest an alternative model, since this approach has some downsides:
You rely on checking equality of users. This limits the user type, e.g., there can't be functions in there.
Looking up a user in a list that doesn't guarantee that all users are different is fragile: If the list happens to end up as [user1, user2, user1, user3], the rotation will never reach user3.
Nothing guarantees that the current user is in the list, hence the Maybe in the return type of the other answers which is hard to deal with correctly.
Thus, let's assume your current model is
type alias Model =
{ currentUser : User
, users : [User]
}
and what you're asking for is
rotateUser : Model -> Model
rotateUser model =
let
nextUser = Maybe.withDefault
model.currentUser
(getNext model.users model.currentUser)
in
{ model | currentUser = nextUser }
getNext : List a -> a -> Maybe a
...
How about instead of implementing getNext, we change the model to make life easier:
type alias Model =
{ currentUser : User
, otherUsers : [User]
}
rotateUser : Model -> Model
rotateUser model =
case model.otherUsers of
[] -> model
(nextUser::rest) ->
{ model
| currentUser = nextUser
, otherUsers = rest ++ [model.currentUser]
}

generating DataFrames in for loop in Scala Spark cause out of memory

I'm generating small dataFrames in for loop. At each round of for loop, I pass the generated dataFrame to a function which returns double. This simple process (which I thought could be easily taken care of by garbage collector) blow up my memory. When I look at Spark UI at each round of for loop it adds a new "SQL{1-500}" (my loop runs 500 times). My question is how to drop this sql object before generating a new one?
my code is something like this:
Seq.fill(500){
val data = (1 to 1000).map(_=>Random.nextInt(1000))
val dataframe = createDataFrame(data)
myFunction(dataframe)
dataframe.unpersist()
}
def myFunction(df: DataFrame)={
df.count()
}
I tried to solve this problem by dataframe.unpersist() and sqlContext.clearCache() but neither of them worked.
You have two places where I suspect something fishy is happening:
in the definition of myFunction : you really need to put the = before the body of the definition. I had typos like that compile, but produce really weird errors (note I changed your myFunction for debugging purposes)
it is better to fill your Seq with something you know and then apply foreach or some such
(You also need to replace random.nexInt with Random.nextInt, and also, you can only create a DataFrame from a Seq of a type that is a subtype of Product, such as tuple, and need to use sqlContext to use createDataFrame)
This code works with no memory issues:
Seq.fill(500)(0).foreach{ i =>
val data = {1 to 1000}.map(_.toDouble).toList.zipWithIndex
val dataframe = sqlContext.createDataFrame(data)
myFunction(dataframe)
}
def myFunction(df: DataFrame) = {
println(df.count())
}
Edit: parallelizing the computation (across 10 cores) and returning the RDD of counts:
sc.parallelize(Seq.fill(500)(0), 10).map{ i =>
val data = {1 to 1000}.map(_.toDouble).toList.zipWithIndex
val dataframe = sqlContext.createDataFrame(data)
myFunction(dataframe)
}
def myFunction(df: DataFrame) = {
df.count()
}
Edit 2: the difference between declaring function myFunction with = and without = is that the first is (a usual) function definition, while the other is procedure definition and is only used for methods that return Unit. See explanation. Here is this point illustrated in Spark-shell:
scala> def myf(df:DataFrame) = df.count()
myf: (df: org.apache.spark.sql.DataFrame)Long
scala> def myf2(df:DataFrame) { df.count() }
myf2: (df: org.apache.spark.sql.DataFrame)Unit

How to filter out "Nothing" values from Elm Array?

I'd like to define the following function:
compactAndConvertToList : Array (Maybe String) -> List String
This function should remove all Nothing appearances in the given array, and convert it to List.
I came up with the solution below, but it feels dirty a bit.
Is there a better way to achieve this?
import Graphics.Element exposing (..)
import Array
model : Array.Array (Maybe String)
model = Array.fromList [ Just "Hello", Just "Stack", Nothing, Just "Overflow" ]
compactAndConvertToList : Array.Array (Maybe String) -> List String
compactAndConvertToList maybeStrings =
maybeStrings
|> Array.filter (\x -> x /= Nothing)
|> Array.map (Maybe.withDefault "")
|> Array.toList
main =
model
|> compactAndConvertToList
|> show
If your final result is a list, you are probably better to just convert your array to a list, and then operate on it.
import Array
compactAndConvertToList : Array.Array (Maybe String) -> List String
compactAndConvertToList = Array.toList >> List.filterMap identity
If you're not comfortable with higher-order functions, you could write it like this:
compactAndConvertToList arr = List.filterMap identity (Array.toList arr)
We take our array, apply toList to it, then apply filterMap with it. Filter map takes a function which produces a maybe, and applies it to every element in the list, discarding the Nothing cases. We just apply the identity functions, which discards the Nothing values that are already there.
In general, Arrays are good for fast random access, but if you're traversing the entire collection a bunch of times, Lists will tend to be faster. But, always start by doing it the clear way, then optimize if you need to.
Maybe this is a better answer as in 2018. Use an elm-community/maybe-extra package.
Example:
Maybe.Extra.values [Just 1, Nothing, Just 3]
Returns:
[1,3]

why both transform and map methods in scala?

I'm having trouble understanding the difference between / reason for, for example, immutable.Map.transform and immutable.Map.map. It looks like transform won't change the key, but that just seems like a trivial variation of the map method. Am I missing something?
I was expecting to find a method that applied a function to the (key,value) of the map when/if that element was accessed (rather than having to iterate through the map eagerly with the map function). Does such a method exist?
You can do exactly that with mapValues. Here is the explanation from the docs:
def mapValues[C](f: (B) ⇒ C): Map[A, C]
Transforms this map by applying a function to every retrieved value.
f - the function used to transform values of this map.
returns - a map view which maps every key of this map to f(this(key)). The resulting map wraps the original map without copying any elements.
edit:
Although extending classes of the collection API is not often a good idea, it could work like this:
class LazilyModifiedMap[A,B,C](underlying: Map[A,B])(f: (A,B) => C) extends Map[A,C] {
def get(key: A) = underlying.get(key).map( x => f(key, x))
def iterator = underlying.iterator.map { case (k,v) => (k, f(k,v)) }
def -(key: A) = iterator.toMap - key
def +[C1 >: C](kv: (A,C1)) = iterator.toMap + kv
}
If you only need the interface of PartialFunction, you can exploit the fact that Map inherits from PartialFunction:
val m = Map(1 -> "foo", 2 -> "bar")
val n = m.andThen(_.reverse)
n(1) // --> oof