Enumerate ImmutableSortedSet from an index - c#

ImmutableSortedSet has an IndexOf and I can enumerate the set with a normal for-loop.
But according to the source code for ImmutableSortedSet it looks like it have to do a tree-search for every index lookup. If I have thousands of items in the set this probably won't be very efficient (and very unnecessary).
Can I somehow get an enumerator from a certain index and forwards? I mean one that just traverses the internal node tree more efficiently?
Perhaps some way of hacking the enumerator with reflection? I kind of want it to fast forward to a certain node and the continue the enumeration from that.
I have attempted to manipulate the "_reverse"-field in the enumerator to first "guide" it to the first node. But I couldn't get the field-change to stick.
Another idea is to populate the node-stack initially as if it already were halfway inside the enumeration, at the point were I want it to start. Just don't know if it is possible.

Related

How to Insert in ConcurrentBag at specified Index and retaining all values?

I would like to get the same behavior as of List.Insert(Index, content )
In List , it just pushes the rest of elements forward while enables you to insert new element at specified index.
But I am dealing Concurrency so I can't use List anymore instead I need to use Concurrent collection. Any idea how we can achieve this?
Note :
I am trying to achieve custom Sorting of custom Objects stored in the concurrent collection( i.e. If at index = 2, Last Name is alphabetically less than the incoming LastName, it must allow the incoming to be placed at index = 2 , while pushing /sliding the old value to next indexes. Thus retaining all contents with new one)
The ConcurrentBag<T> does not provide the functionality that you are looking for. It's not a list, it's a bag. You can't control the order of its contents, and you can't even remove a specific item from this collection. All that you can do is to Add or Take an item.
The rich functionality that you are looking for is not offered by any concurrent collection. Your best bet is probably to use a normal List<T> protected with a lock. Just make sure that you never touch the List<T> outside of a protected region. Whether you need to Add, or Insert, or Remove, or enumerate, or read an item, or read the Count, or anything else, you must always do it inside a lock region that is locked with the same object.
As a side note, it is quite likely that what you are trying to do is fundamentally wrong. There is a reason that the functionality you are asking for is not available: It's practically impossible to use it in a meaningful way without introducing race-conditions. For example two threads could independently figure out that they must insert a new item in the index 5, based on the existing values in the list, and then both try to inserting it at this index, concurrently. Both will succeed, but one of the two items will end-up in the index 6 after being pushed by the other item, and the two items might not be in the correct order in respect to each other.

is Dictionary.Keys order guarantee to be the same if the Dictionary has not been modified?

based on the doc
The order of the keys in the Dictionary.KeyCollection is
unspecified
Ok I'm fine with that. But what if I did not modify the dictionary's key nor its values.
Lets say if I do
Dictionary.Keys.ToList();
Thread.Sleep(5000)
Dictionary.Keys.ToList();
can I safely assume the order would be the same?
Iterating a Dictionary is a deterministic process. It is based on the implementation-specific way the items are organized inside hash "buckets", tie resolution, and insertion order.
However, the order of iterating a dictionary does not depend on anything arbitrary that could change between iterations. You can see how the iteration is done in the source of Dictionary.Enumerator here: its bool MoveNext() method walks dictionary.entries[index] array one by one, stopping when the first unused element is reached. Hence you can safely assume that the order of iterating a dictionary is not going to change when you do not modify the dictionary between iterations.

Poor use of dictionary?

I've read on here that iterating though a dictionary is generally considered abusing the data structure and to use something else.
However, I'm having trouble coming up with a better way to accomplish what I'm trying to do.
When a tag is scanned I use its ID as the key and the value is a list of zones it was seen in. About every second I check to see if a tag in my dictionary has been seen in two or more zones and if it has, queue it up for some calculations.
for (int i = 0; i < TagReads.Count; i++)
{
var tag = TagReads.ElementAt(i).Value;
if (tag.ZoneReads.Count > 1)
{
Report.Tags.Enqueue(tag);
Boolean success = false;
do
{
success = TagReads.TryRemove(tag.Epc, out TagInfo outTag);
} while (!success);
}
}
I feel like a dictionary is the correct choice here because there can be many tags to look up but something about this code nags me as being poor.
As far as efficiency goes. The speed is fine for now in our small scale test environment but I don't have a good way to find out how it will work on a massive scale until it is put to use, hence my concern.
I believe that there's an alternative approach which doesn't involve iterating a big dictionary.
First of all, you need to create a HashSet<T> of tags on which you'll store those tags that have been detected in more than 2 zones. We'll call it tagsDetectedInMoreThanTwoZones.
And you may refactor your code flow as follows:
A. Whenever you detect a tag in one zone...
Add the tag and the zone to the main dictionary.
Create an exclusive lock against tagsDetectedInMoreThanTwoZones to avoid undesired behaviors in B..
Check if the key has more than one zone. If this is true, add it to tagsDetectedInMoreThanTwoZones.
Release the lock against tagsDetectedInMoreThanTwoZones.
B. Whenever you need to process a tag which has been detected in more than one zone...
Create an exclusive lock against tagsDetectedInMoreThanTwoZones to avoid more than a thread trying to process them.
Iterate tagsDetectedInTwoOrMoreZones.
Use each tag in tagsDetectedInMoreThanTwoZones to get the zones in your current dictionary.
Clear tagsDetectedInMoreThanTwoZones.
Release the exclusive lock against tagsDetectedInMoreThanTwoZones.
Now you'll iterate those tags that you already know that have been detected in more than a zone!
In the long run, you can even make per-region partitions so you never get a tagsDetectedInMoreThanTwoZones set with too many items to iterate, and each set could be consumed by a dedicated thread!
If you are going to do a lot of lookup in your code and only sometimes iterate through the whole thing, then I think the dictionary use is ok. I would like to point out thought that your use of ElementAt is more alarming. ElementAt performs very poorly when used on objects that do not implement IList<T> and the dictionary does not. For IEnumerables<T> that do not implement IList the way the nth element is found is through iteration, so your for-loop will iterate the dictionary once for each element. You are better off with a standard foreach.
I feel like this is a good use for a dictionary, giving you good access speed when you want to check if an ID is already in the collection.

Fastest way to get any element from a Dictionary

I'm implementing A* in C# (not for pathfinding) and I need Dictionary to hold open nodes, because I need fast insertion and fast lookup. I want to get the first open node from the Dictionary (it can be any random node). Using Dictionary.First() is very slow. If I use an iterator, MoveNext() is still using 15% of the whole CPU time of my program. What is the fastest way to get any random element from a Dictionary?
I suggest you use a specialized data structure for this purpose, as the regular Dictionary was not made for this.
In Java, I would probably recommend LinkedHashMap, for which there are custom C# equivalents (not built-in sadly) (see).
It is, however, rather easy to implement this yourself in a reasonable fashion. You could, for instance, use a regular dictionary with tuples that point to the next element as well as the actual data. Or you could keep a secondary stack that simply stores all keys in order of addition. Just some ideas. I never did implemented nor profiled this myself, but I'm sure you'll find a good way.
Oh, and if you didn't already, you might also want to check the hash code distribution, to make sure there is no problem there.
Finding the first (or an index) element in a dictionary is actually O(n) because it has to iterate over every bucket until a non-empty one is found, so MoveNext will actually be the fastest way.
If this were a problem, I would consider using something like a stack, where pop is an O(1) operation.
Try
Enumerable.ToList(dictionary.Values)[new Random().next(dictionary.Count)].
Should have pretty good performance but watch out for memory usage if your dictionary is huge. Obviously take care of not creating the random object every time and you might be able to cache the return value of Enumerable.ToList if its members don't change too frequently.

timing how long an element has been in a list

What would be the easiest way to track how long an element has been part of a list? For instance, I would like to pop an element from a list after it has been added for 2 minutes.
Would I have to create two lists, one holding the actual element and the other the time that element was added to the list? Then checking the "time" list in order to know when it has reached two minutes?
I have a feeling theres a much simpler and efficient method to do this but I cannot think of it at the moment...
If you want to have the minimum amount of code to write, you can have a look at the MemoryCache class, which implements an expiration policy.
Using the CacheItemPolicy you can even have a callback method executed when the item is removed after expiration.
Rather than storing the elements in the lists directly, you could use a wrapper class which included the element and its storage time, then store instances of the wrapper class instead.
You would probably want to use a queue rather than a list; you will be removing items from the front a lot, which is far more efficient with a queue than with a list.
How often you check the queue is something you'd need to decide on. You could possibly use a separate thread to check every so often, in which case you'd probably want to use a ConcurrentQueue<T>

Categories