I have an array which is dynamic, and key and values are displaying in order if they are set. I want to display keys of this array in my own order, What kind of condition must I write in this case?
Take a look at the Core Utility Libraries, namely the sort() method of the Set class. Check for more info the cookbook.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 months ago.
Improve this question
What is the difference between an array, an ordered collection of integer-indexed values, and a hash, a collection of key-value pairs, where every key is an index that starts from zero?
arr = [1,2,3,4]
hash = { 0 => 1, 1 => 2, 2 => 3, 3 => 4}
I know that it would be stupid to implement a hash like that, but what is the difference behind the hood? Are they stored in different ways in memory? What data structure makes your program faster when retrieving data from it?
Speed
Arrays are a better for iterating over a collection.
Hashes have almost constant lookup time O(log n), while Arrays have linear time O(n).
This means that you should prefer Hashes when you need to use #include?.
Hashes work great as dictionaries.
There is a third underutilised data structure in Ruby which behaves like a unique Array but uses a Hash underneath. This is Set. It works great when you don't care about the order of elements, need to check if something belongs to a group or need a unique collection of elements.
Implemetation
Yes, they are two completely different data structures.
In this particular example you could access these elements in a similar manner by calling arr[0] and hash[0].
The line arr[0] is in fact sugar syntax for arr.[](0). Same goes for arr[0] = 5 which is the same as arr.[]=(0, 5). Both Array and Hash have methods called [] and []=, but under the hood completely different things would happen, because these are two separate methods with the same name.
Arrays are always indexed with integers starting with 0 and the order of items is important.
Array is a simple list of elements backed by a dynamic C array, while a Hash is an implementation of a dictionary/hashmap, a much more sophisticated data structure.
Hashes store both keys and values, and possess the ability to retrieve a value based on the received key. Every single Ruby object that implements #eql? and #hash can become a Hash key.
The order of elements in a Hash can change and is not stable.
Every Hash is in fact an array of slots called buckets. These buckets hold individual key-value pairs. To determine which key should correspond to a certain bucket, Ruby uses a hashing function, provided by the method called #hash on the object passed as the key. If two objects return the same value from their #hash method, they are considered the same key.
This goes both ways, Ruby uses #hash to save the key-value pair in the right bucket, and to find the right value for the passed key.
For example "string".hash will always return the same value, even though these are different objects.
This value is calculated based on the content of the String. This is why Strings with the same content (even though they are different objects) are considered the same key in a Hash.
Sometimes two different objects (of separate classes) end up having the same #hash. Ruby handles these collisions by implementing individual buckets as linked lists of key-value pairs. So a few key-value pairs may be stored in the same bucket.
To decide which value should be returned for a given key, when there are a few key-value pairs in the same bucket, Ruby utilises the eql? method.
It compares each key stored in the bucket with the passed key like so passed_key.eql?(key_in_bucket). When they are equal Ruby considers them a match.
Here's a great article on Hashes.
Almost every object in Ruby has a hash method. This method calculates some number which is unique-ish. That number is used to retrieve a key in a Hash object. If you want to get the value for 2 then the hash value for 2 is calculated (for an integer this is really fast) and looked up in the Hash object. So it looks like a hash is a way to over-complicate things - but if you want to be sure, benchmark your use-case is the way to go.
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).
How can I write a NSPredicate that will check if all the elements in an NSArray are the same? I need this for a more complex predicate that I am using to filter NSTableView.
NSPredicate can't tell you if all the items are the same, but you could use it to filter an array for objects that are not equal to object[0]. This wouldn't be particularly performant since it would have to check the entire contents of the array.
You could instead use - (void)enumerateObjectsWithOptions: then bailing out when you find a different object via *stop = YES.
Consider looking at using NSSet, since that is designed to store a collection of unique objects (albeit unordered).
Without knowing more detail it's impossible to say what is the best solution for you.
i knew its a weird Idea to think about, i want to know if it is possible to reverse the mechanism of sorting, (i dont want to reverse the order).
for example lets say i have a random array of integers, then i sorted the array with quicksort method, now i want to go back and un-sort the array and get it back to the it was.
you may suggest i save a copy of the array, thats not what i want, think of it as a time line and have the ability to go backward or forward of sorting method.
and if it is possible please consider showing me the best way to do it with Delphi XE.
Thanks in advance.
It is not possible to unsort. You have to either:
create a separate array that holds a copy of the values and then sort that array so that you can preserve the original array.
create a separate array that holds pointers/indexes to the values in the original array, and then sort the second array using the values it refers to.
I usually use a function that given an array returns an array of the sorted indexes.
This way you will always have the original data and you will be able to access the data in a sorted way using something like:
for jIndex in ASortedIndexesArray do
ShowMessage(AOriginalArray[jIndex]);
Hope this helps.
Mirko
If you want to think of it as a time line and have the ability to go backward or forward of sorting method then organize it like a timeline - with records in a file. Save each step and you will be able to reproduce it.
If the array is of integers the indices will not help you as one index (a pointer) takes the same memory as one array element. If you lack RAM use a file to store and retrieve the array. If you use larger data structures you can create, store and retrieve indices as David suggested.
You could log the swapping actions that quicksort (or whatever sorting algorithm you use) does to a list and then go forward and backward in that list to undo/redo these actions. Not simple to implement, but doable.
I have a scope object that has a list containing null values, I would like to sort this list in both directions but the null values must be always at the end. I can probably do this easily by splitting up the object into 2, one with nulls and one without then stick on the null list at the end. But is there a more efficient way to do this?
example:
[1,null,5,7,2,null]
sorted:
ASD: 1,2,5,7,null,null
DESC: 7,5,2,1,null,null
If you just want to sort the array, JavaScript has method array.sort. This takes a comparer function.
You can implement two of such functions one for ascending sorting and one for descending. Within these two functions you can treat nulls as you wish. See documentation here
If you are using angularjs filter orderby it too takes a comparer function, so a similar approach may work.