So I've been learning crystal without a ruby background and noticed the api docs have #dup and #clone for basically copying an array.
What exactly is the difference between the two? The api says #dup shallow copies the array whilst #clone deep copies said array. I'm not sure what exactly that entails and which one I should be using.
#dup will duplicate the array in memory, that is the list of items it contains, but it won't duplicate the items themselves. Mutating the new array won't affect the previous array(e.g. push, pop) but mutating any of its items will affect the item of the previous array since the items are the same objects.
#clone will duplicate the array list in memory, but also its items, by calling #clone recursively. This is a full clone of the original array. Mutating anything, even a deep nested object, won't affect the original content.
Note that this applies to any object, not just arrays, and that the behavior can be customised by overriding the methods in your own objects.
That being said, it only applies for arrays of objects (e.g. class instances). For arrays of primitives (integer, float, struct...) the items will be copied along with the array list by #dup.
Related
I'm using OpenRefine to pull in information on publisher policies using the Sherpa Romeo API (Sherpa Romeo is a site that aggregates publisher policies). I've got that.
Now I need to parse the returned JSON so that those with certain pieces of information remain. The results I'm interested in need to include the following:
'any_website',
'any_repository',
'institutional_repository',
'non_commercial_institutional_repository',
'non_commercial_repository'
These pieces on information all fall under an array called "permitted_oa". For some reason, I can't even work out how to just pull out that array. I've tried writing grel expressions such as
value.parseJson().items.permitted_oa
but it never reutrns anything.
I wish I could share the JSON but it's too big.
I can see a couple of issues here.
Firstly the Sherpa API response items is an array (i.e. a list of things). When you have an array in the JSON, you either have to select a particular item from the array, or you have to explicitly work through the list of things in the array (aka iterate across the array) in your GREL. If you've previously worked with arrays in GREL you'll be familiar with this, but if you haven't
value.parseJson().items[0] -> first item in the array
value.parseJson().items[1] -> second item in the array
value.parseJson().items[2] -> third item in the array etc. etc.
If you know there is only ever going to be a single item in the array then you can safely use value.parseJson().items[0]
However, if you don't know how many items will be in the array and you are interested in them all, you will have to iterate over the array using a GREL control such as "forEach":
forEach(value.parseJson().items, v, v)
is a way of iterating over the array - each time the GREL finds an item in the array, it will assign it to a variable "v" and then you can do a further operation on that value using "v" as you would usually use "value" (see https://docs.openrefine.org/manual/grel#foreache1-v-e2 for an example of using forEach on an array)
Another possibility is to use join on the array. This will join all the things in an array into a string.
value.parseJson().items.join("|")
It looks like the Sherpa JSON uses Arrays liberally so you may find more arrays you have to deal with to get to the values you want.
Secondly, in the JSON you pasted "oa_permitted" isn't directly in the "item" but in another array called "publisher_policy" - so you'll need to navigate that as well. So:
value.parseJson().items[0].publisher_policy[0].permitted_oa[0]
would get you the first permitted_oa object in the first publisher_policy in the first item in the items array. If you wanted to (for example) get a list of locations from the JSON you have pasted you could use:
value.parseJson().items[0].publisher_policy[0].permitted_oa[0].location.location.join("|")
Which will give you a pipe ("|") separated list of locations based on the assumption there is only a single item, single publisher_policy and singe permitted_oa - which is true in the case of the JSON you've supplied here (but might not always be true)
I have a UITableViewController that can display content from any of three different arrays. In Objective-C, what I would typically do is set a property on the TableVC that is a reference to the array to be displayed. Then the TableVC would not only be able to show the contents of that array, but also handle user-directed editing of the array, say, if they deleted or re-ordered elements.
The way it seems to work in Swift when I set a property on my TableVC to an array is that it is a copy of my model's array, not a reference. And while this is fine in certain contexts, in my application it seems bad for two reasons: 1) my arrays are enormous, thousands of elements, and copying huge arrays over and over again seems wasteful; 2) small edits are tougher to handle: I have to communicate back to the model about element deletion or re-ordering and make sure my view and model arrays stay in sync.
Setting a property that's a reference to an array is what I want to do, but there's no such thing as an inout object property in Swift.
What is the correct way for me to handle this?
Thanks.
Swift Arrays are not actually copied every time you assign them; instead, they are copy-on-write. What this means is that the array is only copied when something mutates it; until that point, you only copy a reference, like with Objective-C.
With that said, if you need reference semantics, the NSArray class from Objective-C is still available in Swift. You can also create your own class type that wraps an Array if you prefer not to use the Objective-C bridge.
I have a dictionary like [String:[MyClass]] and I want to access each value in each array in the dictionary, but without any copying.
Can I do this with for..in? Or maybe the forEach method does the job?
You can just iterate normally with for..in and not worry about the value copying mechanics. If you are interested in what's happening under the hood, look up copy-on-write behaviour, which Swift arrays adopt.
The gist of it is: A copy of the array (or any other data structure that implements copy-on-write) will only be created in memory when you modify that array. If it doesn't mutate, the two array instances will still use the same underlying memory.
As per the documentation,
observable.map(values?) creates a dynamic keyed observable map.
Observable maps are very useful if you don't want to react just to the
change of a specific entry, but also to the addition or removal of
entries.
I may be the only one who doesn't understand the difference between these two mobx observable types. Even the doc says map can track addition or removal, following array also notifies the console by autorun when a new value is pushed into the array. So what is the real difference between the two?
window.q = observable([1,2,3]);
autorun(()=>{console.log(q[0]);})
q.push(32)
The difference is in the methods you use to interact with them. Think of one as an array, and the other as a map. Arrays stores indices, maps store keys and values.
I was reading an article about array vs list, and the author says that an array is worse than a list, because (among other things) an array is a list of variables, but to me a list is also a list of variables. I mean, I can still do list[3] = new Item().
Actually, I have always somehow saw a List<T> like a wrapper for an array that allows me to use it easily without caring about handling its structure.
What are the internal differences between a T[] and a List<T> in terms of heap/stack memory usage?
Since an array is a static structure, after the initialization, it allocates the memory that you've demanded.
int arr[5];
For example here there are 5 int objects created in memory. But when you use lists, according to its implementation, it gives you first an array with predefined capacity. And while you are adding your elements, if you exceed the capacity then it scales up. In some implementations it just doubles its size, or in some implementations it enlarges itself when the granted capacity is half full.
The author's point about a "list of variables" wasn't about memory. It's that an array contains your internal variables, and returning it allows them to be reassigned by the caller. It comes down to this:
Only pass out an array if it is wrapped up by a read-only object.
If you pass out an internal List<T>, you have the same problem, but here's the key:
We have an extensibility model for lists because lists are classes. We
have no ability to make an “immutable array”. Arrays are what they are
and they’re never going to change.
And, at the time the article was written, the IReadOnlyList interface didn't exist yet (.NET 4.5), though he probably would have mentioned it if it had. I believe he was advocating implementing an IList<T> that would simply throw an exception if you tried to use the setter. Of course, if the user doesn't need the ability to access elements by index, you don't need a list interface at all -- you can just wrap it in a ReadOnlyCollection<T> and return it as an IEnumerable<T>.