Ordered collection based on DateTime - c#

I'm looking for a way to implement a collection which guarantees order based on a DateTime value. My initial idea was to use a SortedSet<T1> with a custom IComparer<T1> like this:
internal class DateTimeComparer : IComparer<MyType> {
public int Compare(MyType x, MyType y) {
return x.DateTimeProp.CompareTo(y.DateTimeProp);
}
}
var sortedSet = new SortedSet<MyType>(new DateTimeComparer());
However this doesn't work as the set seems to override/replace all items which have the exact timestamp. To validate this assumption, I created two collections, one being a simple list which was sorted using the DateTime property after its was populated, and another one based on the SortedSet<T1> -> The one based on the set had several entries missing which happened to be the ones which had the exact same timestamp.
What other options are there to implement such a collection?

An efficient way to maintain a sorted collection of items is to use a binary search tree. You could of course build your own binary search tree, however the SortedSet<T> class is implemented using a red-black binary search tree so it seems smarter to reuse that class which is exactly what you are trying to do.
The ordering of items in SortedSet<T> is controlled by comparing pairs of items by calling the IComparer<T>.Compare method. If this method returns 0 the two items are considered equal and only one of these items will be stored in the set. In your case with DateTimeComparer you get the problem that only a single MyType instance with a specifiec DateTimeProp can be stored in the set.
To solve this problem you have to make sure that distinct MyType instances never are equal when compared using the DateTimeComparer.Compare method. You can modify your code to achieve this:
class DateTimeComparer : IComparer<MyType> {
readonly ObjectIDGenerator idGenerator = new ObjectIDGenerator();
public int Compare(MyType x, MyType y) {
if (x.DateTimeProp != y.DateTimeProp)
return x.DateTimeProp.CompareTo(y.DateTimeProp);
bool firstTime;
var xId = idGenerator.GetId(x, out firstTime);
var yId = idGenerator.GetId(y, out firstTime);
return xId.CompareTo(yId);
}
}
If the two instances have different values of DateTimeProp then they should be ordered according to these. This is handled by the initial if statement.
If the two values have the same DateTimeProp values they need to be ordered based on some other criteria. You can use other properties of MyType but there might be cases where these properties are equal and it is important that the method never returns 0 except if x and y refers to the same instances (e.g. ReferenceEquals(x, y) is true).
To handle this you can use an ObjectIDGenerator which will assign unique 64 bit ID values to distinct instances. These can then be compared to provide an ordering.
Note that the ordering of items with same DateTimeProp values will be random but consistent. To control this ordering you can use other properties of MyType but eventually you will have to use the generated ID to provide an ordering when all properties of two different instances are the same.

Related

Reflection: Get properties/fields from individual elements of a List<>

I'm sorry in advance for the mess you're about to read, because I'm not 100% sure what I'm searching for.
I have created an entire UI system that automatically grabs a list of properties from various scripts/components on GameObjects (Unity) and creates a fitting UI input variant for them (for example, float gets a single line, Vector3 gets 3 lines, color gets something else etc.).
What goes into UI input fields creation is a Component (that we want to look into), while individual created UI inputs store this Component and Property Name. So when input changes in one of input fields, it does SetValue on Property of a Component. Now I have also created a variant where we peak into a Class of a property and basically list Property's Properties, so the UI input stores Component, Property Name, and subProperty's Name and modifies properties as such. All this works well.
So, now I hit a brick wall with Lists. I would like to treat individual elements of a list as properties so that I could pass them into my preexisting UI scheme.
tl;dr Does List<> treat it's individual elements as Properties, Fields or does it depend on the situation? How do I get these properties, fields or their respective names from this list in order to use them with my mess of an UI system? 0 work for me means treating individual elements of List as properties.
----------------------------
EDIT----------------------------
Again I am sorry for this mess of a question. It is a mixture of confused theory and description of an existing situation that I am trying to shoehorn into my already existing project (which is a bit too over the place to be easily reduced to an example).
If anyone grasped what I was asking for, the single easiest solution was to create a property which prior to listing was equated to an element of a list.
Example looks something like this:
public List<MyCustomClass> myCustomList;
[Listable("ForEdit")]
public myCustomClass myCustomPropertyForEdit
{
get;
set;
}
And before withdrawing properties of myCustomPropertyForEdit's class (myCustomClass) I would simply do:
myCustomPropertyForEdit = myCustomList[0]; //or whatever index is in question
Then later on I would do reflection on "myCustomPropertyForEdit" instead of myCustomList. I highly doubt this will ever help anyone because it touches more onto how I built methods for listing properties into my UI, but there it is just in case.
List stores references to objects, by providing an index you get a standard object reference, which you can proceed to query using reflection (do not do it against the list itself as you will get methods of the List class, and notthing related to what the list contains)
take for example:
public Class Tree
{
public int branches;
public Tree(int branch)
{
branches=branch;
}
}
List<Tree> trees = new List<Tree>();
trees.Add(new Tree(3));
now my list has one element at index 0;
so i can do trees[0].branches;
to access the fields/props of an element in trees.
list is not an array, it holds the actual item, allowing you to reference, not just the object but also its own unique variables. as long as they are public in the class.

Comparing Items in two ObservableCollections

I have two ObservableCollections, one that contains a current list of employees and one that contains a new one. If the new one contains an employee that is not in the old list, I want to add it to the old list.
If the new list does not contain an employee in the old list, I want to remove it from the old list. (I hope that makes sense).
Here is what I have tried;
foreach (var employee in _currentUsers.ToList())
{
if (!newUsers.Contains(employee))
{
Dispatcher.Invoke(() =>
{
_currentUsers.Remove(employee);
CurrentUsageDataGrid.Items.Refresh();
});
}
}
foreach (var employee in newUsers)
{
if (!_currentUsers.Contains(employee))
{
Dispatcher.Invoke(() =>
{
_currentUsers.Add(employee);
CurrentUsageDataGrid.Items.Refresh();
});
}
}
This is not working as even when I know that the lists haven't changed the Dispatcher.Invoke() is still firing. Am I misunderstanding how Contains operates and/or is there a 'better' way of performing a check like this?
Does your employee class implement IEquatable<T> interface, the method Contains of ObservableCollection will use Equal in that interface to compare object.
Otherwise you may need to use Linq to check for existing employee instead of using Contains
More reference on MSDN, https://msdn.microsoft.com/en-us/library/ms132407(v=vs.100).aspx
As was mentioned above you need to implement/override an Equal method for the comparison. When you do a "Contains" check on 2 class objects, it checks if the 2 objects are equal (not if their properties are). You can do the equal using an id, or you could compute a hashvalue and compare those.

Data collection with 3 elements per entry

Is there a data collection in the .net framework (ideally in collections.generic that can deal with three disparate objects (lets say int,string and float) whereby the other two elements can be accessed given one of the elements (assuming every object is unique).
I don't know if this would exist, or even if it could be created, but ideally it would work similarly to a Dictionary<key,value> but would in essence be Collection <key,key,key> sort of arrangement that could be used like Collection[key].third = data.
As I said, I have no idea if this sort of arrangement exists; if it does, could you please point me in the correct direction, if not, could you please let me know if there are any ideas of how this could be achieved.
Thanks in advance.
The closest data structure out-of-the-box to what you are looking for is List<Tuple<int, string, float>>. You can easily use linq to search for objects that match criteria for any of the three parts.
However, it would not be a significant amount of work to create a custom type that represents your element:
public class Element
{
public int IntValue {get; set;}
public string StringValue {get; set;}
public float FloatValue {get; set;}
}
A multi-key dictionary wouldn't be terribly hard, either - just override the indexer for each type. Note that all three types must be distinct, or you will get compiler errors since the compiler won't know which indexer you are binding to.
The advantage is that you can use appropriate names for each value - what does the int value represent? That's one big advantage a custom class has over Tuple is context.
I would also note that "equality" for float values can be tricky. two float values that seem to be equal can in reality be very slightly different. Floating-point values are often compared by looking within a range for a specified tolerance. As such they generally make poor keys for indexed structured like Dictionary.

Multi-sorted data structure

I'm trying to implement A* and I ran into a problem. I have a set where I need to find the minimum value of a given function, but I also need to be able to check if a given cell is in that set. In order to do this efficiently, I need the set to be sorted by position and value. It doesn't seem too difficult to write such a data structure. I just need one sorted by position and one by value, and have each refer to the other. There are two problems with this. First, in order to do it well, the structures need to be able to refer to parts of each other. There's no point in searching through a tree in log time if I can just point to the particular element. In order to do this, I'd pretty much need to rewrite trees from scratch. Second, it doesn't seem like the sort of thing I should be writing. Data structures are supposed to be part of the libraries. What's the name of the sort of data structure I need, and where can I find a C# library for it?
There is no need for the two data structures to interact at all. Just have two data structures side by side. Make sure that when you add/remove an item you add/remove it from both. You can then fetch the minimum value of either collection based on which property you're interested in.
The only real reason to create a new data structure would be to ensure that adding/removing items was kept in sync between the two collections. There would be no need to manipulate the actual trees explicitly.
Such a custom type would look something like this (other operations omitted; they all just delegate to first and/or second).
public class SetPair<T>
{
private SortedSet<T> first;
private SortedSet<T> second;
public SetPair(IComparer<T> firstComparer, IComparer<T> secondComparer)
{
first = new SortedSet<T>(firstComparer ?? Comparer<T>.Default);
second = new SortedSet<T>(secondComparer ?? Comparer<T>.Default);
}
public T FirstMin { get { return first.Min; } }
public T SecondMin { get { return second.Min; } }
public bool Add(T item)
{
return first.Add(item) &&
second.Add(item);
}
public bool Remove(T item)
{
return first.Remove(item) &&
second.Remove(item);
}
}

Removing items found in another list

I have two lists and they are named: currentItems and newItems. newItems contains items found in currentItems and I am trying to those items before I output the list.
I have done some searching and I have tried using:
var newList = newItems.Except(CurrentItems).ToList();
but when I look at the output I still find the items from currentItems in the list. I found this example when I came across this question:
Quickest way to compare two List<>
which is similar to what I am trying to achieve but the all answers to the question do not work for me.
I have tried using:
List<ListItem> newList = newItems.Union(CurrentItems).ToList();
but I believe I am using it in the wrong situation since I am trying to remove the item completely from the list.
I have also tried looping through both loops, but I don't believe that is as efficient as it can be.
In the first example is there something I may be doing wrong with it? Or is there a different way to achieve my goal?
IEnumerable.Except will do what you want but it uses the default equality comparer. For custom objects you will need to implement Equals and GetHashCode
Also note that if newItems has duplicate values IEnumerable.Except will also do a distinct on your list.
EDIT2: You need an equality comparer that compares ListItem's I believe.
You'll need to pass in a custom comparor that compares just the Value property of the ListItem.
var newList = newItems.Except(currentItems, new ListItemValueComparer());
And the custom equality comparer is here...
class ListItemValueComparer : IEqualityComparer<ListItem>
{
public bool Equals(ListItem x, ListItem y)
{
return x.Value.Equals(y.Value);
}
public int GetHashCode(ListItem obj)
{
return obj.Value.GetHashCode();
}
}

Categories