Concise way to change object across multiple arrays - arrays

I'm looking to know if changing an object in one array will change it in others.
I have an array of tasks, each of which is a hash object with :id, :user, :task
I then use duplicates = tasks.select{|task| sample code} to select some tasks from that array.
If I change a task in duplicates, will it change in tasks as well? If not, are there any good ways to search for that same task?

There is no such thing as "changing an object across arrays". An object does not know and does not care whether it is in an array or not.
Changing an object changes an object. Period. If that object is contained in multiple arrays, then you will observe that change, regardless of how you obtain the object. But it is not "changed across arrays". It is simply changed.
If you cut your hair, everybody who looks at you will observe that your hair is short, regardless of whether they perceive you as "student #1234", "the quarterback of the Backwater Swamprats", or "the youngest son of the Smith family". What reference is used to address you has no bearing on whether your hair is short or not.

Related

How to create an Array (IDataHolder) in Thinkscript? (Thinkorswim)

I am trying to create an irregular volume scanner on Thinkorswim using Thinkscript. I want to create an array of volume's in past periods so that I can compare them to the current period's volume (using fold or recursion). However, while the Thinkorswim documentation details what is called an IDataHolder datatype, which is an array of data, I cannot find how one can actually create one, as opposed to just referencing the historical data held by Thinkorswim. Here is the documentation: https://tlc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder
I have tried coding something as simple as this to initialize an array:
def array = [];
This throws an error. I have tried different types of brackets, changing any possible syntax issues, etc.
Is this possible in the Thinkscript language? If not, are there any workarounds? If not even that, is there a third party programming interface that I could use to pull data from Thinkorswim and get a scanner that way? Thanks for any help.
IDataHolder represents data such as close, open, volume, etc, that is held across multiple bars or ticks. You can reference one of these pre-defined data series, or you can create your own using variables: def openPlus5cents = open + 0.05, say, would be an IDataHolder type value.
There's no way to create an array in the usual programming sense, as you've found, so you'll have to be a little creative. Perhaps, say, you could do the comparison within the fold? volume[1] > volume, or the like? Maybe post another question with an example of the comparison you're trying to do?

How can I read a parameter array from excel so that its values are available when stocks are initialized?

The problem:
I need to read a row of values from an excel spreadsheet into a parameter array and use these values to set the initial values of stocks.
The specifics:
a. I can successfully set the scalar parameters default values from excel using ExcelControlName.getCellNumericValue("ExcelSheetName", RowNumber, ColumnNumber).
b. Trying to set default values for array parameters with ExcelControlName.readHyperArray(DestinationArrayName,"ExcelSheetName",RowNumber, ColumnNumber, false) returns a "Cannot return a void result" error on build.
c. I can read the parameter arrays from a function called from the Agent actions "On startup:" section using ExcelControlName.readHyperArray(DestinationArrayName,"ExcelSheetName",RowNumber, ColumnNumber, false).
d. Stocks with their initial values set to the parameter array that was successfully loaded by the function are all zero even though the parameter array shows values (when run). Initial value: ParameterArrayName.
e. When I set the parameter array values through the value editor the stocks initialize correctly.
My suspicion:
I'm thinking that the issue has something to do with the internal timing within the entrails of the model generated by Anylogic such that the function to load the parameters is executed after the stocks get initial values - but that could just be the delirium caused by repeatedly smashing my forehead into the wall. But, if this is indeed the case, how can I sneak the function in earlier or, better yet, how would someone who actually knows what they're doing accomplish this?
What I'm trying to accomplish:
As a septuagenarian with lots of time on my hands and a vague recollection of dynamic modeling using Dynamo from a Systems Science program in the early seventies (and not used since), I thought I'd take a whack at age-based modeling of the COVID-19 pandemic. I wanted to see, among other things, whether establishing elder-prisons (in now vacant Club-Meds, Sandals... I'm sure) would be an economically advantageous strategy. Getting there requires dis-aggregating classic SIR approaches into age-specific chains of causality. So far, I'm at 27 age-specific parameters for eight age-groups and 24 scalar parameters. As much as I'd like to type and retype... all this data I'm really hoping there is a better way.
I must say that I am amazed at how far modeling has come in only 50 or so years and I am enthralled with Anylogic's application - even though it's a bit java-ish for me.
Thank you ever so much,
Carl Cottrell
Equivalent parameter arrays - one with values entered in edit the other read from excel file through a function
Not sure if I understand but here it goes:
I understand that you have the following structure:
and you want to initialize the stock as follows.
To do that, on the initial value of your parameter use a function that returns an HyperParameter:
the function getInitialValue should return an HyperParameter and I think this code should work for you (you have to choose RowNumber according to whatever is on your excelfile, MyDimension is the name of your dimension, and ExcelControlName is the excel in which you hold the values of the initial values of the stock)
HyperArray x=new HyperArray(MyDimension);
for(int i=0;i<=numColumns;i++){
x.set(ExcelControlName.getCellNumericValue("ExcelSheetName", RowNumber, i), i);
}
return x;

How to access an element in 2d array in Smalltalk

I started coding in Smalltalk and got stuck here. I have this 2d array:
testArr := Array new: 1.
testArr at: 1
put: ((Array new: 3)
at: 1 put: '1A';
at: 2 put: '1B';
at: 3 put: '1C';
yourself).
But if I want to access lets say first element of first array, what should I write to make it happen?
Thanks!
I'm tempted to take advantage of your question & answer, and elaborate a little bit on knowledge that belongs in the Smalltalk folklore (which you may already be aware of).
As we progresses in the use of Smalltalk, we will likely note that the Array class starts to play a decreasing role in our models. Why is that? Because it takes time to find out which are the objects our models will produce; the balance between too many and too few is a delicate matter, mostly clueless at the beginning.
Arrays and their composition are handy data structures. However, they solve the problem of organizing data at the expense of dealing with it. If the client of such a structure needs to know how data is stored as a prerequisite to act on it, then the message paradigm becomes semantically idle.
Let's imagine a matrix object. There are several ways to keep their entries: a one-dimensional array, an array of rows, an array of columns, a dictionary of (sparse) non-null entries, a triangular structure if the matrices are known to be symmetric/anti-symmetric/Hermitian, and a lot more for special cases. Of course, this variety makes no sense for the problem at hand and, in any case, it would be a bad idea to spend time considering the most general approach: In Smalltalk, generality is attained at the message, not at the storage.
Regardless of the internal organization of data, our objects should always offer protocols that are independent of the underlying structure. Back to the matrix example, even if our initial organization is an array of rows, the matrix object should work the same whether rows are arrays or more sophisticated vector objects that are also used for other ends. This means that when coding the internal access to entry (i,j) we should pretend we don't know the class of row i but only the message to access its jth element. Something on the lines of
atRow: i column: j
| row |
row := self row: i.
^row at: j
Here we are not assuming that row is an Array; we are only assuming that it understands the at: message, which is the least we can assume when talking to a row object, whatever its actual nature. Of course, this code is only good under the assumption that rows are not recreated on the fly, as they would, had our class kept instead collections of columns. But this is ok, otherwise we would only need to add another class and override this and some few other low level messages.
In any case, the idea is to defer as much as possible any explicit knowledge about the internal organization so that it gets confined to a few private messages. One way to test we are applying this good practice is to make sure no low level code repeats in two or more methods. For instance, the use of the row: message above moves low level code away from atRow:column:, deferring it to another that makes sense for the (ideal) matrix protocol.
This example illustrates an important point: be suspicious of any code that needs to compose two at: messages. And --why not-- enjoy the beauty of not having to declare types.
So, the problem was in brackets.
^(testArr at: 1) at:1
returns
1A
as I needed.

Avoiding database when checking for existing values

Is there a way through hashes or bitwise operators or another algorithm to avoid using database when simply checking for previously appeared string or value?
Assuming, there is no way to store whole history of the strings appeared before, only little information can be stored.
You may be interested in Bloom filters. They don't let you authoritatively say, "yes, this value is in the set of interest", but they do let you say "yes, this value is probably in the set" vs. "no, this value definitely is not in the set". For many situations, that's enough to be useful.
The way it works is:
You create an array of Boolean values (i.e. of bits). The larger you can afford to make this array, the better.
You create a bunch of different hash functions that each take an input string and map it to one element of the array. You want these hash functions to be independent, so that even if one hash function maps two strings to the same element, a different hash function will most likely map them to different elements.
To record that a string is in the set, you apply each of your hash functions to it in turn — giving you a set of elements in the array — and you set all of the mapped-to elements to TRUE.
To check if a string is (probably) is in the set, you do the same thing, except that now you just check the mapped-to elements to see if they are TRUE. If all of them are TRUE, then the string is probably in the set; otherwise, it definitely isn't.
If you're interested in this approach, see https://en.wikipedia.org/wiki/Bloom_filter for detailed analysis that can help you tune the filter appropriately (choosing the right array-size and number of hash functions) to get useful probabilities.

Complexity on sorting or not an integer array

I have an array of integers storing some userIDs. I basically want to prevent a user from performing an action twice, so the moment he has done it his userID enters this array.
I wonder whether it is a good idea to sort or not this array. If it is sorted, then you have A={min, ..., max}. Then, if I'm not wrong, checking if an ID is in the array will take log2(|A|) 'steps'. On the other hand, if the array was not sorted then you will need |A|/2 (in average) steps.
So sorting seems better to check if an element exists in the array (log(|A|) vs |A|), but what about 'adding' a new value? Calculating the position of where the new userID should be can be done at the same time you're checking, but then you will have to displace all the elements from that position by 1... or at least that's how I'd do it on C, truth is this is going to be an array in a MongoDB document, so perhaps this is handled in some other most-effective way.
Of course if the array is unsorted then adding a new value will just take one step ("pushing" it to the end).
To me, an adding operation (with previous checking) will take:
If sorted: log2(|A|) + |A|/2. The log2 part to check and find the place and the |A|/2 as an average of the displacements needed.
If not sorted: |A|/2 + 1. The |A|/2 to check and the +1 to push the new element.
Given that for adding you'll always first check, then the not sorted version appears to have less steps, but truth is I'm not very confident on the +|A|/2 of the sorted version. That's how I would do it in C, but maybe it can work another way...
O(Log(A)) is definitely better than O(A), but this can be done in O(1). The data structure you are looking for is HashMap, if you are going to do this in C. I haven't worked in C in a very long time so I don't know if it is natively available now. It surely is available in C++. Also there are some libraries which you can use in the worst case.
For MongoDB, my solution may not be the best, but I think that you can create another collection of just the userIDs and index the collection keyed on userIDs. This way when someone tries to do that action, you can query the user status quickest.
Also in MongoDB you can try adding another key called UserDidTheAction to your User's collection. This key's value may be true or false. Index the collection based on userID and probably you will have similar performance as the other solution, but at the cost of modifying your original collection's design (though it's not required to be fixed in MongoDB).

Resources