Elm: Fold specific values of multiple lists - elm

games =
[ { id = 1
, points =
[ { player_id = 1, score = 20 }
, { player_id = 2, score = 10 }
, { player_id = 3, score = 0 }
]
}
, { id = 2
, points =
[ { player_id = 1, score = 20 }
, { player_id = 2, score = 5 }
, { player_id = 3, score = 0 }
]
}
, { id = 3
, points =
[ { player_id = 1, score = 20 }
, { player_id = 2, score = 5 }
, { player_id = 3, score = 10 }
]
}
]
I have a list of 'games' records which each have a list of points for each player.
Is it possible to fold each score of each player across each game to display a 'total'.
Something like:
[ { player_id = 1, score = 60 }
, { player_id = 2, score = 20 }
, { player_id = 3, score = 10 }
]
Thanks in advance.

You need a double fold, where the key code is
main : Html msg
main =
let
go { points } acc =
let
goInner { player_id, score } accInner =
Dict.update player_id (updater score) accInner
in
List.foldl goInner acc points
in
List.foldl go Dict.empty games
|> toString
|> text
updater : Int -> Maybe Int -> Maybe Int
updater score existingVal =
existingVal
|> Maybe.withDefault 0
|> (+) score
|> Just
See [https://ellie-app.com/gq8VFfS8Ja1/0](this ellie)
This gets you the answer you want albeit in a slightly different format

Related

Add element to list on update, together with other changes in a record

I have the following initialModel,
initialModel : Model
initialModel =
{ cards =
[ { url = "Gita.jpg", card = 1, selected = False }
, { url = "Kali.jpg", card = 2, selected = False }
, { url = "Arjuna.jpg", card = 3, selected = False }
, { url = "Krishna.jpg", card = 4, selected = False }
, { url = "Manjusri.jpg", card = 5, selected = False }
, { url = "siddartha.jpg", card = 6, selected = False }
, { url = "bodhidharma2.jpg", card = 7, selected = False }
]
, selectedCards = [ "card1" ]
, activeCard = ""
}
And I have them hooked with onClick,
type Msg
= ClickedCard { url : String, id : String }
| Other
update : Msg -> Model -> Model
update msg model =
case msg of
ClickedCard data ->
{ model
| activeCard = data.id
, selectedCards = selectedCards ++ data.id -- This line is pseudo-code
}
_ ->
model
How can I make that update work? So, in the end, every click on a new card should make it on the selectedCards list.

Check Value in Dict

Trying to check the value of fruit
fruit =
Dict.fromList
[ ( 1, { fruitIsGood = False } )
, ( 2, { fruitIsGood = False } )
, ( 3, { fruitIsGood = True } )
]
whichFruitIsGood : Dict.Dict number { fruitIsGood : Bool } -> String
whichFruitIsGood fruit =
case get 0 fruit of
Nothing ->
Debug.crash "nothing found"
Just fruit ->
if fruit.fruitIsGood == True then
"Apple"
else
"I hate Fruit"
I don't know how to get at the fruitIsGood prop or whatever you call it in Elm here..
First, Debug.crash "nothing found" won't provide to you any useful functionality, what about returning nothing found string instead.
Then you just need to fix the errors, which the compiler points out. They are mostly about the variables, which are defined multiple times. Let's rename your first function to fruits:
fruits =
Dict.fromList
[ ( 1, { fruitIsGood = False } )
, ( 2, { fruitIsGood = False } )
, ( 3, { fruitIsGood = True } )
]
And a variable in the second function:
whichFruitIsGood : Dict.Dict number { fruitIsGood : Bool } -> String
whichFruitIsGood fruit =
case get 3 fruit of
Nothing ->
"nothing found"
Just foundFruit ->
if foundFruit.fruitIsGood == True then
"Apple"
else
"I hate Fruit"
Then your code will compile and return nothing found as a result.
Here's a small a bit modified ellie-app example, which shows the code in action.

Get List inside List

I have a complex data structure and I had to create this short example for better understanding.
type alias People =
{ name : String
, sex : String
, phones : List Phone
}
type alias Phone =
{ number : String
, isActive : Bool
}
This structure populated:
people = [
{ name = "_me"
, sex = "M"
, phones = [
{ number = "(99) 99 9 9999-9999"
, isActive = True
}]
},
{ name = "_you"
, sex = "M"
, phones = [
{ number = "(11) 11 1 1111-1111"
, isActive = True
},
{ number = "(22) 22 2 2222-2222"
, isActive = False
}]
}]
And I would like to get only the 'phones' from the 'people' list, as in the example below
phones = [
{ number = "(99) 99 9 9999-9999"
, isActive = True
},
{ number = "(11) 11 1 1111-1111"
, isActive = True
},
{ number = "(22) 22 2 2222-2222"
, isActive = False
}]
I've been trying for 3 days, but to no avail.
You can pull out all the phone numbers into a list by mapping over to get the phone number list of a person, then concatenating those phone number lists together:
getPhones : List People -> List Phone
getPhones = List.concat << List.map .phones

Applying Maybes When Updating A Model

I want to update my model this way:
updatedModel =
if model.firstChord && model.secondChord then
{ model | firstChord = {}, secondChord = {} }
else
model
the firstChord and the secondChord both are of the type Chord:
type alias Chord =
{ root : Maybe Pitch
, third : Maybe Pitch
, fifth : Maybe Pitch
}
The pitch type looks like:
-- pitch
type alias Pitch = ( PitchName, PitchLevel )
-- pitch name
type alias PitchName = String
-- pitch level
type alias PitchLevel = Int
My initial Model has these fields:
{ firstChord =
{ root = ( "C", 3 )
, third = ( "E", 3 )
, fifth = ( "G", 3 )
}
, secondChord =
{ root = ( "F", 3 )
, third = ( "A", 3 )
, fifth = ( "C", 4 )
}
I like to have optional pitch values.
How can I update my model giving it a value OR nothing?
Thanks.
Not quite sure what are you looking for. I guest you would like to have a Maybe Chord like this.
type Pitch =
Pitch String Int
type alias Chord =
{ root: Maybe Pitch
, third: Maybe Pitch
, fifth: Maybe Pitch
}
type alias Model =
{ firstChord: Maybe Chord
, secondChord: Maybe Chord
}
init: Model
init =
{ firstChord =
{ root = Pitch "C" 3
, third = Pitch "E" 3
, fifth = Pitch "G" 3
}
, secondChord =
{ root = Pitch "F" 3
, third = Pitch "A" 3
, fifth = Pitch "C" 4
}
}
update: Model -> Model
update model =
case (model.firstChord, model.secondChord) of
(Just first, Just second) ->
{ model | firstChord = Nothing, secondChord = Nothing}
_ ->
model
When you have a Maybe a type, such as Maybe Pitch you have two ways to set its value: Nothing or Just a. So instead of this:
{ firstChord =
{ root = ( "C", 3 )
, third = ( "E", 3 )
, fifth = ( "G", 3 )
}
, secondChord =
{ root = ( "F", 3 )
, third = ( "A", 3 )
, fifth = ( "C", 4 )
}
...you need to do this:
{ firstChord =
{ root = Just ( "C", 3 )
, third = Just ( "E", 3 )
, fifth = Just ( "G", 3 )
}
, secondChord =
{ root = Just ( "F", 3 )
, third = Just ( "A", 3 )
, fifth = Just ( "C", 4 )
}
Of course, you then use Nothing so indicate no value:
firstChord =
{ root = Just ( "C", 3 )
, third = Just ( "E", 3 )
, fifth = Nothing
}

Select all objects with font-size between two sizes in illustrator?

I need to select all text-objects with a size between two values, for example 12 and 14pt (including 12.1, 12.2 etc). Is this at all possible?
This seems to be the candidate for a script. Try this:
function selectTextWhosePointSizeIs ( minPointSize, maxPointSize )
{
var doc, tfs, i = 0, n = 0, selectionArray = [];
if ( !app.documents.length ) { return; }
doc = app.activeDocument;
tfs = doc.textFrames;
n = tfs.length;
if ( !n ){ return; }
if ( isNaN ( minPointSize ) )
{
alert(minPointSize + " is not a valid number" );
return;
}
else if ( isNaN ( maxPointSize ) )
{
alert(maxPointSize + " is not a valid number" );
return;
}
else if ( minPointSize > maxPointSize )
{
alert(minPointSize + " can't be greater than "+ maxPointSize);
return;
}
for ( i = 0 ; i < n ; i++ )
{
if ( tfs[i].textRange.size >= minPointSize && tfs[i].textRange.size <= maxPointSize )
{
selectionArray [ selectionArray.length ] = tfs[i];
}
}
if ( selectionArray.length )
{
app.selection = selectionArray;
}
else
{
alert("Nothing found in this range.");
}
}
selectTextWhosePointSizeIs ( 12, 14 );
Hope it helps,
Loic