Code:
let studentMap =
for i = 0 to count do
Map.empty.Add(students.[i].getId(), students.[i].getScores())
I am trying to add to a map sequentially. I have student objects in an array and am trying to add them in order. I am confused at how to do this. I thought maybe you make an empty map then add to it in order via a for loop, but it always causes trouble and won't work. Is there a way to add items to a map using a for loop? The <key/value> pairs are this: <string, int array>. That is the way I want it formatted but it keeps giving me trouble. I'll restate the goal again to clarify: I want to be able to add items to a map using a for loop with my student objects array being used to get the appropriate data I need in there. I will be able to give it a string and get back that student's grades for example. I know it's a weird problem I'm working on, but I needed to try something simple at first.
You can try a more functional idiomatic approach:
Let's say you have an array of type Student (in the example below is an empty array):
let students = Array.empty<Student>
You can transform your array in to a Map:
let mapStudents = students
|> Array.map (fun s -> (s.getId(), s.getScore()))
|> Map.ofArray
You could use a mutable map variable:
let studentMap =
let mutable m <- Map.empty
for i = 0 to count do
m <- m.Add(students.[i].getId(), students.[i].getScores())
m
or a mutable dictionary:
let studentMap =
let m = new System.Collections.Generic.Dictionary<int, Scores>()
for i = 0 to count do
m.Add(students.[i].getId(), students.[i].getScores())
m
a more functional solution would be to use a fold:
let studentMap = seq { 0 .. count } |> Seq.fold (fun (m: Map<int, Scores>) i -> m.Add(students.[i].getId(), students.[i].getScores())) Map.empty
I think the Map.ofArray approach is probably the best, but it is worthwhile to point out that the for loops can done a bit better:
let map = new System.Collections.Generic.Dictionary<int, Scores>()
for student in students do
map.Add(student.getId(), student.getScore())
This neatly avoids making array bounds mistakes.
In functional languages, the built-in data structures are immutable, that is, when you add an element, a new value of the data structure is returned.
If you want to convert one structure to another, you can often use one of the build-in functions like Map.ofArray. If you have a more complex scenario, like a function generating your values, then you can use a 'loop', and each iteration of the loop returns a new value of the data structure. The way to express such a 'loop' in a functional way, is to use a recursive function:
let studentMap =
let rec loop currentMap i =
if i >= count then currentMap
else
let newMap = Map.add (students.[i].getId()) (students.[i].getScores()) currentMap
loop newMap (i+1)
loop Map.empty 0
Now you have full flexibility in how you generate the values (they don't have to be part of an array) and you're avoiding mutable variables that are un-idiomatic in functional programming. Ideally, like in this case, the function should be tail-recursive to allow tail-call optimisation (and avoid stack overflow for large inputs).
Related
Hi i am struggling to get my array in Pinescript to produce anything other than a list of Nan. I am trying to create an array of the % difference of the low and 20sma when price bounces off the 20sma but currently when i print the array it only has Nan values.
sma_20 = sma(close,20)
sma_20_touch_band = open>sma_20 and low<=sma_20
sma_20_dif = ((low-sma_20)/sma_20)
sma_20_array = array.new_float(100)
if sma_20_touch_band
array.push(sma_20_array, sma_20_dif)
array.shift(sma_20_array)
That is most likely caused by not using a var array. Without the var keyword, your array will be re-initialized on each bar. You need to initialze your array once, and manipulate its elements later on. Therefore make it:
var sma_20_array = array.new_float(100)
Also, I'm not so sure about your usage of the array.shift() function.
You push something to the array, but with the array.shift() you remove the first element from the array. At the end of the day, you remove what you have just added. At least this is what I think is happening.
this is my first question so i hope I am doiung the tagging and so on right.
I have an array of objects of the same class. When I want to access a property of the objects I can use:
Data = [ObjectArray.property];
Now I want to call a mehtod of the class for each object and get back the result as Vektor/ matrice:
result = [ObjectArray.myfun(X)]
here I get an error saying:
Expected one output from curly brace or dot indexing expression
I tried brute force several different annotation but nothing works and i can't find a solution online.
Anybody knows how to make this work?
Thanks and Cheers!
It's slightly unclear what the structure of your array is, but you should be able to use arrayfun.
result = arrayfun( #(obj) obj.myfun(x), ObjectArray );
If you function myfun returns anything other than a scalar, you will need to set the UniformOutput flag to be false. This will make the result a cell array, with one cell per result.
result = arrayfun( #(obj) obj.myfun(x), ObjectArray, 'uni', false );
% If you want to concatenate results, could use something like
% result = [result{:}];
Note that this is basically shorthand for a loop, but it saves you pre-allocating an output and writing the loop.
You can also do this directly inside of your myfun:
If the item you operate your method on is an array, the first parameter of your myfun method will be an array. This can be used, and call itself one by one:
vec = [MyClass(1), MyClass(2)];
list = vec.myfun();
classdef MyClass
properties
prop1
end
methods
function obj = MyClass(val)
obj.prop1 = val;
end
function val = myfun(obj)
if numel(obj) > 1
val = arrayfun(#(o) o.myfun(), obj);
return;
end
val = obj.prop1;
end
end
end
I have a variable as follows
local armies = {
[1] = "ARMY_1",
[2] = "ARMY_3",
[3] = "ARMY_6",
[4] = "ARMY_7",
}
Now I want to do an action for each value. What is the best way to loop over the values? The typical thing I'm finding on the internet is this:
for i, armyName in pairs(armies) do
doStuffWithArmyName(armyName)
end
I don't like that as it results in an unused variable i. The following approach avoids that and is what I am currently using:
for i in pairs(armies) do
doStuffWithArmyName(armies[i])
end
However this is still not as readable and simple as I'd like, since this is iterating over the keys and then getting the value using the key (rather imperatively). Another boon I have with both approaches is that pairs is needed. The value being looped over here is one I have control over, and I'd prefer that it can be looped over as easily as possible.
Is there a better way to do such a loop if I only care about the values? Is there a way to address the concerns I listed?
I'm using Lua 5.0 (and am quite new to the language)
The idiomatic way to iterate over an array is:
for _, armyName in ipairs(armies) do
doStuffWithArmyName(armyName)
end
Note that:
Use ipairs over pairs for arrays
If the key isn't what you are interested, use _ as placeholder.
If, for some reason, that _ placeholder still concerns you, make your own iterator. Programming in Lua provides it as an example:
function values(t)
local i = 0
return function() i = i + 1; return t[i] end
end
Usage:
for v in values(armies) do
print(v)
end
I have the following (imperative) algorithm that I want to implement in Haskell:
Given a sequence of pairs [(e0,s0), (e1,s1), (e2,s2),...,(en,sn)], where both "e" and "s" parts are natural numbers not necessarily different, at each time step one element of this sequence is randomly selected, let's say (ei,si), and based in the values of (ei,si), a new element is built and added to the sequence.
How can I implement this efficiently in Haskell? The need for random access would make it bad for lists, while the need for appending one element at a time would make it bad for arrays, as far as I know.
Thanks in advance.
I suggest using either Data.Set or Data.Sequence, depending on what you're needing it for. The latter in particular provides you with logarithmic index lookup (as opposed to linear for lists) and O(1) appending on either end.
"while the need for appending one element at a time would make it bad for arrays" Algorithmically, it seems like you want a dynamic array (aka vector, array list, etc.), which has amortized O(1) time to append an element. I don't know of a Haskell implementation of it off-hand, and it is not a very "functional" data structure, but it is definitely possible to implement it in Haskell in some kind of state monad.
If you know approx how much total elements you will need then you can create an array of such size which is "sparse" at first and then as need you can put elements in it.
Something like below can be used to represent this new array:
data MyArray = MyArray (Array Int Int) Int
(where the last Int represent how many elements are used in the array)
If you really need stop-and-start resizing, you could think about using the simple-rope package along with a StringLike instance for something like Vector. In particular, this might accommodate scenarios where you start out with a large array and are interested in relatively small additions.
That said, adding individual elements into the chunks of the rope may still induce a lot of copying. You will need to try out your specific case, but you should be prepared to use a mutable vector as you may not need pure intermediate results.
If you can build your array in one shot and just need the indexing behavior you describe, something like the following may suffice,
import Data.Array.IArray
test :: Array Int (Int,Int)
test = accumArray (flip const) (0,0) (0,20) [(i, f i) | i <- [0..19]]
where f 0 = (1,0)
f i = let (e,s) = test ! (i `div` 2) in (e*2,s+1)
Taking a note from ivanm, I think Sets are the way to go for this.
import Data.Set as Set
import System.Random (RandomGen, getStdGen)
startSet :: Set (Int, Int)
startSet = Set.fromList [(1,2), (3,4)] -- etc. Whatever the initial set is
-- grow the set by randomly producing "n" elements.
growSet :: (RandomGen g) => g -> Set (Int, Int) -> Int -> (Set (Int, Int), g)
growSet g s n | n <= 0 = (s, g)
| otherwise = growSet g'' s' (n-1)
where s' = Set.insert (x,y) s
((x,_), g') = randElem s g
((_,y), g'') = randElem s g'
randElem :: (RandomGen g) => Set a -> g -> (a, g)
randElem = undefined
main = do
g <- getStdGen
let (grownSet,_) = growSet g startSet 2
print $ grownSet -- or whatever you want to do with it
This assumes that randElem is an efficient, definable method for selecting a random element from a Set. (I asked this SO question regarding efficient implementations of such a method). One thing I realized upon writing up this implementation is that it may not suit your needs, since Sets cannot contain duplicate elements, and my algorithm has no way to give extra weight to pairings that appear multiple times in the list.
I am currently trying to figure out how to design some sort of loop to insert data into an array sequentially. I'm using Javascript in the Unity3D engine.
Basically, I want to store a bunch of coordinate locations in an array. Whenever the user clicks the screen, my script will grab the coordinate location. The problem is, I'm unsure about how to insert this into an array.
How would I check the array's index to make sure if array[0] is taken, then use array[1]? Maybe some sort of For loop or counter?
Thanks
To just add onto the end of an array, just use .push().
var myArray = [];
var coord1 = [12,59];
var coord2 = [87,23];
myArray.push(coord1);
myArray.push(coord2);
myArray, now contains two items (each which is an array of two coordinates).
Now, you wouldn't do it this way if you were just statically declaring everything as I've done here (you could just statically declare the whole array), but I just whipped up this sample to show you how push works to add an item onto the end of an array.
See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push for some reference doc on push.
In case you need to know the array's length when reading the array in the future, you can use the .length attribute.
var lengthOfArray = myArray.length;
Using the .push() method as suggested by jfriend00 is my recommendation too, but to answer your question about how to work out what the next index is you can use the array's length property. Because JavaScript arrays are zero-based The length property will return an integer one higher than the current highest index, so length will also be the index value to use if you want to add another item at the end:
anArray[anArray.length] = someValue; // add to end of array
To get the last element in the array you of course say anArray[anArray.length-1].
Note that for most purposes length will give the number of elements in the array, but I said "one higher than the current highest index" above because JavaScript arrays are quite happy for you to skip indexes:
var myArray = [];
myArray[0] = "something";
myArray[1] = "something else";
myArray[50] = "something else again";
alert(myArray.length); // gives '51'
// accessing any unused indexes will return undefined