Data collection with 3 elements per entry - c#

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.

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.

Ordered collection based on DateTime

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.

How to store an IEnumerable and a string that describes it together

The IEnumerable in question is a list of an object containing filenames and properties relating to those file names, and the string is a directory name, such as "C:\Test\Testing". My goal is to store these two pieces of data together so that they're 'linked', in a sense, which should make them easier to use together, as the IEnumerable will become the source for a DataGrid, and the string the text of a label stating the current directory.
How would I go about achieving this? I initially thought of a dictionary, but that doesn't seem to work here. I need to be able to grab the 'top-most' item, so to speak, whenever a button is pressed, and dictionaries are, I believe, unordered.
While the accepted answer works, I would recommend creating a class for this, rather than using a KeyValuePair:
public class FilesInDirectory
{
public string Directory { get; set; }
public IEnumerable<string> FileNames { get; set; }
}
In OOP you should strive to avoid primitive obsession. A KeyValuePair is a kind of primitive, as it doesn't convey any meaning and can't be extended.
Meaning: When you're iterating over the list and dealing with item.Key and then iterating over item.Value, things will get confusing - far less so than item.Directory and item.FileNames
Extension: You will want to define some methods that extract data from these items, or process them in some way - usually, these methods are better off on the data item itself. For example you might want to get a list of actual file objects. With a KeyValuePair, you will have to define that method on some other class, whereas it actually fits right at home on FilesInDirectory.GetFiles()
How about a List<KeyValuePair<IEnumerable, string>>?
var list = new List<KeyValuePair<IEnumerable, string>>();
list.Add(new KeyValuePair<IEnumerable, string>(data, path));
If that sounds too awkward for you, feel free to use a custom class instead.
Feel free to use a Queue<>, Stack<> or anything else that fits your needs, KeyValuePair can be used with any collection type.

Multiple choice enum

I am lately starting a project and I have a question.
Let's say I am dealing with a class Person, and a person can have one(or more) deseases he is encountering.
so I have created an enum :
public enum diseases{headache,throat,bruise,gunshot,none}; // enum containing all the diseases
public diseases disease;
And further in code I set a certain disease to that person and it works fine.
Thing is, there might be a point in my project where a person might have 2 diseases.
So there are my questions:
Is using enum the best option here? I want my code to be organized and understood and that's a main reason for using enums.
If using enum is a good option, I have managed to combine this enum with bit-flags(using [System.Flags]) so when time comes I can check for a disease that contains two different values from the enum. is this a good approach?
If using enum is a good option, should I just create a second property from diseases (just like I created disease) and save all the trouble from using bit-flags?
Thanks in advance for any light on that matter, couldn't figure what was the best approach here.
A good option would to make a List<diseases> to hold for a single person.
public class Person
{
public string Name { get; set; }
public List<diseases> Diseases { get; set; }
public Person(string name)
{
this.Name = name;
Diseases = new List<diseases>();
}
}
This way you can enumerate over all the values relatively easily without having to worry about flags.
For example:
var bob = new Person("bob");
bob.Diseases.Add(diseases.gunshot);
var hasHeadache = bob.Diseases.Any(x => x == diseases.headache);
An enum is a plausible (yet a bit simplistic) way to represent one disease.
If someone may have N diseases, then just use a container of objects of that type, such as a list. But you need to choose the right container. A list of diseases may be, for example: { headache, throat, headache, throat, gunshot }. Lists allow duplicates. Whay you may actually need is a set of diseases. A set is a structure which does not allow duplicates.
The choice of how you represent one disease and the fact that a person may have N diseases, so that you need a person to have a container of diseases, are two totally independent facts.
Use the FlagsAttribute on your enum.
[Flags]
Public enum diseases
{
// your values here
}
This should give you what you need.
There is a lot of opinion being asked for here and the right answer is that it depends on a lot of variables what solution is right in any given situation. You CAN use an ENUM to represent multiple values so long as the [Flags] attribute is given to the ENUM. Keep in mind that if you decide to go that route then you are responsible for assigning the values of the ENUM specific non-overlapping values like 1, 2, 4, 8, 16, 32, etc.
Is using enum the best option here? - This depends on how many diseases you would like to cover. If the number is small (10..20) and the list is flat (no hierarchy of diseases) then you are fine. Otherwise, consider some alternative.
is [System.Flags] a good approach? - Yes, in case of a small, flat, list [System.Flags] approach is very good and extremely efficient.
Should I just create a second property from diseases and save all the trouble from using bit-flags? Having a second property in place of running a collection is a terrible idea. If you have to do something twice, chances are, you'd do it N times. Make a collection or bit fields, never go for a second property unless the system is inherently limited to two items (say, a binary tree).
If the list of diseases is not "flat" (e.g. you plan to have ViralThroat, BacterialThroat, and ThroatInjury in place of a simple throat that you have now) you would be better off modeling diseases as classes, and creating a collection of diseases attached to a Person. You could add methods for checking the collection for particular diseases, which could be smart about the search: for example, find any kind of throat sub-disease when a throat is passed as a search criterion.
enum is just one of many perfectly acceptable options here. Others include OO solutions such as base/derived classes, or simple lists of string (or event lists of enums, why not?!). Often the simplest approach is best. We would have to know a lot more about your problem to recommend one over the other.
While using Flags is one solution, I would not recommend it in this case. Flags are not verbose on what they are for. Any time I used flags, I would have to re-learn how to properly work with flags when I needed to modify my code. One simple alternative is creating a property for each possible disease...
public class Diseases
{
public bool Headache {get;set;}
...
public bool HasAnyDisease() { return Headache || Throat || ...;}
}
But that has it's downsides as well. It's not easily extensible. I would recommend using the Decorator Pattern. Each disease could decorate the class which may make future interactions with it easier to maintain. If you need to have variance disease combinations cause different outcomes, this may be better in the long run.

c# Tuple - What is a practical use of Tuple [duplicate]

This question already has answers here:
What and When to use Tuple? [duplicate]
(5 answers)
Closed 8 years ago.
I was looking at examples online of Tuple but I do not see any ideal use of it.
Meaning, it seems like a place to store variables.
Is there any practical use of Tuple. What I like to do is to pass in a value to the tuple and then have it return back 3 values which are all strings.
A Tuple is counter-part to a List.
While a List stores 0-N of the same type of item, a Tuple store 1-M of (possibly) different-typed items, where N is unbounded and M is statically fixed/defined.
Each of these items can be accessed in a strongly-typed manner by their name (or "index" as it happens to aligned).
They are thus similar to an anonymous type (actually, this is more like a "record" and not a "tuple" because the names can be arbitrarily chosen):
new { _0 = value0, _1 = value1, /* etc, as needed */ }
But the Tuple types are nominatively typed (they are backed by a bunch of different classes, just like Action or Func) and thus a specific Tuple type can be explicitly specified (e.g. in method signatures), which is something an anonymous type cannot be used for.
While I would say that the practical use of Tuples in C# is hampered by the lack of support (e.g. no decomposition, no application, etc.), they are used all the time in languages like Scala. The C# approach is generally to "create a new named type", but introduces the Tuple types as another available tool.
(A big place where Tuples are very useful is in intermediate computations -- but C# has anonymous types, which as seen with LINQ, fulfill this role quite well in most cases where the computations are done within the same method.)
Microsoft .NET 4.0 introduces type called Tuple which is a fixed-size collection of heterogeneously typed data. Like an array, a tuple has a fixed size that can't be changed once it has been created. Unlike an array, each element in a tuple may be a different type, and a tuple is able to guarantee strong typing for each element. This is really handy in scenario otherwise be achieved using custom types or struct.
Tuple s a container. you can store anything in it
For 3 items, it s called Triple. 4 items quadruple and so on.
Essentially you can just stick items in to it.
Here is an example.
The Tuple is a typed, immutable and generic construct. It is a useful container for storing conceptually related data. A simple class with commented members and additional methods is more useful for important things. But the Tuple can be used to store miscellaneous yet related information. Tuple falls short in the field of information hiding. It excels as a useful short-term container.
A practical use-case: let's say you want to pass around a list of structured data between different internal components of a software.
You can either declare a class which represents the structured data. In this case this class has to be dumb ideally, it'll only contain a bunch auto properties. You probably declare this in an interface as an embedded class (but then you have to prefix it with the interface name), or in the same namespace as the interface. At some point this maybe unnecessary plumbing code to define a sole class for this purpose.
Or you can use a tuple. This way you don't have to define a class for all of that, you can still remain type safe. You may loose the advantage of naming the properties, which can be problematic if you have many properties, maybe even from the same type.
More concrete example:
You want to set a column sorting for a TreeListView 3rd party component. You initiate the sorting from the controller object, which calls the right function (SortByColumns) on the view, which calls the function on your wrapper class around the 3rd party component, which calls the 3rd party components' proper functions.
If you define a DTO (dtata transfer object) object:
// Somewhere around an interface
class ColumnSortItem
{
string Caption { get; set; }
SortOrder Order { get; set; }
}
// Other places:
void SortByColumns(IList<ColumnSortItem> pColumnSortItems);
Tuples:
void SortByColumns(IList<Tuple<string, SortOrder>> pColumnSortItems);
I don't say tuples are always the better choice, but notice that we just had to declare a certain order and structure of items. Note, that in this concrete example it's pretty clear what is the string part of the tuple and what is the SortOrder part.
Addition: the actual calls of the function:
DTO
controller.SortByColumns(new List<ColumnSortItem>() {
new ColumnSortItem() { Caption = "Record", Order = SortOrder.Ascending },
new ColumnSortItem() { Caption = "Description", Order = SortOrder.Ascending }
});
Tuple
controller.SortByColumns(new List<Tuple<string, SortOrder>>() {
new Tuple<string, SortOrder>("Record", SortOrder.Ascending),
new Tuple<string, SortOrder>("Description", SortOrder.Ascending)
});
Tuple is a lightweight class to group several items together. It's an alternative to defining a new class any time you want to group two items together.
I find it useful when I want to return multiple items from a single method, but I can't use ref or out parameters.
It seems like it's there for temporary data storage; very localized use. These are occasions when writing your own class is either too time consuming or really not worth it because the data's life time is so short.
The .NET Framework 4 introduce the System.Tuple class for creating tuple objects that contain structured data. It also provides generic tuple classes to support tuples that have from one to eight components .
Here is example in C#
var objTupe = new System.Tuple<string, string, double,long>"Mike","Anderson",29000,9999999999);
Response.Write("Item1 : " + objTupe.Item1);
Response.Write("<br/>Item2 : " + objTupe.Item2);
Response.Write("<br/>Item3 : " + objTupe.Item3);
Response.Write("<br/>Item4 : " + objTupe.Item4);

Categories