In project I often use "containers" that store different number of values that have various types.
For example for 2 and 3 values:
class Nodes2<K, V> {
public K Key { get; set; }
public V Value { get; set; }
}
class Nodes3<T1, T2, T3> {
public T1 Value1 { get; set; }
public T2 Value2 { get; set; }
public T3 Value3 { get; set; }
}
Then I use them in collections:
List<Nodes3<int, string, double>> descriptions = new List<Nodes3<int, string, double>>();
That well suites for simple cases, when there is no neŃessity for create individual class for every such case.
So, the question is: are there in .NET built-in classes that can hold values like in my case?
Yes, there are. For key-values you have Dictionary<K,V>.
For node holders, you have Tuple (All the way up to 8 elements). Although a bit cumbersome (IMO), you can use them an access your items via Item1, Item2, etc.
And you use them like this:
var tuple = Tuple.Create("Hello", 0);
var hello = tuple.Item1;
var zero = tuple.Item2;
Yes, Tuple, with it's implementations with extra generic type parameters. (Tuple<T>, Tuple<T1, T2>, etc.). Tuple is available from .NET 4.
From MSDN:
var tuple1 = Tuple.Create(12);
Console.WriteLine(tuple1.Item1)
And:
var tuple2 = Tuple.Create("New York", 32.68);
Console.WriteLine("{0}: {1}", tuple2.Item1, tuple2.Item2);
And so on.
There's already a class made for this Tuple.
List<Tuple<int, string, double>> lists = new List<Tuple<int, string, double>>();
lists.Add(Tuple.Create<int, string, double>(5, "string", 10d));
Related
I am searching for a solution to create List<> of Lists with different data types like
List<List<int>,List<double>,List<string>> list;
or a List<> with multiple data types like
List<int,double,string> list;
In all seriousness... why?
The code which consumes these structures is going to be confusing and difficult to support. It really, really will.
If you have a custom structure to your data, create a custom object to represent that structure. Something like this:
class MyThing
{
public int Widget { get; set; }
public double Foo { get; set; }
public string Something { get; set; }
}
Use actual meaningful names for your values/types/etc. of course, because that's the entire point of doing this.
Then just have a list of those:
var things = new List<MyThing>();
As your structure continues to change and grow, you build the logic of that structure into the object itself, rather than into all of the consuming code which uses it. The code which uses it then more closely approximates the semantics of the operations it's trying to perform, rather than a dizzying assortment of syntactic operations.
May be you can do like this
public class Helper
{
public object value;
private string Type;
}
then create list
List<Helper> myList=new List<Helper>();
use like this
myList.Add(new Helper {value = 45,Type = "int"});
myList.Add(new Helper {value = 45,Type = "int"});
myList.Add(new Helper {value = "hello",Type = "string"});
and the covert according to Type.
You can make a list of lists by
List<List<int>>
To have a list with multiple data types you could use a Tuple which can take up to 8 items.
List<Tuple<string, int>>
List<Tuple<string, string, int>>
You could even go crazy and do the following
Tuple<List<int>, int, int> tuple = new Tuple<List<int>, int, int>(new List<int>(), 2, 3);
If I'm understanding you correctly, I think you need a little helper class:
public class MyInfo {
public int MyInt32 { get; set; }
public double MyDouble { get; set; }
public string MyString { get; set; }
}
Then, make a list of those: var myList = new List<MyInfo>().
You can also use a List<Tuple<int, double, string>>, but I would recommend creating your own class if the scope of usage is wider than a single class, because Tuples properties aren't very descriptive as to what they are: Item1, Item2, Item3...
Best way to solve this is to use Interface you can find solution here list of multiple data types
You can use ArrayList - the old non generic list. THis allows you to put anything in it, int, string, FooObject, bool,....
I was wondering if there's a simpler way to do this using LINQ or some other way...
I want to extract, from a List, all rows, grouping them by a particular field and storing the result in another different, like a List containing the grouped, not repeated, result of the search parameter.
Here's an example:
public class CustomObj
{
public int DOC { get; set; }
public string Desc { get; set; }
public string Name{ get; set; }
}
public class Worker()
{
public void DoWork()
{
List<CustomObj> objs = new List<CustomObj>();
objs.Add(new CustomObj(1, "Type1", "Name1"));
objs.Add(new CustomObj(1, "Type2", "Name1"));
objs.Add(new CustomObj(2, "Type2", "Name2"));
objs.Add(new CustomObj(3, "Type1", "Name1"));
objs.Add(new CustomObj(3, "Type2", "Name1"));
objs.Add(new CustomObj(3, "Type3", "Name1"));
// HERE'S WHAT I'D LIKE TO DO
// NOTE THAT THIS IS NOT A CORRECT FORMATED FUNCTION
List<int> docs = objs.GroupBy(o => o.DOC).Select(o => o.DOC).ToList<int>();
}
}
At the end my docs List should look like this
docs[0] = 1
docs[1] = 2
docs[2] = 3
In my current project I have, so far, 10 different objects, and I'm going to have to do this to all of them. Of course I'd like to avoid writing extensive functions to each one.
So if there's no other way at least I would like to know.
Thanks
What about:
List<int> docs = objs.Select(o => o.DOC).Distinct().ToList();
Or, if you want to use GroupBy:
var docs = objs.GroupBy(o => o.DOC).Select(o => o.Key).ToList();
I have a situation where I need a class which need to contain information about something which varies at runtime, for example:
class Info<T>
{
public T Max { get; set; }
public T Min { get; set; }
public T DefaultValue { get; set; }
public T Step { get; set; }
// Some other stuff
}
I have to store many instances of this class in a dictionary but problem is that to use dictionary I have to declare one type e.g.
Dictionary<string, Info<int>> dict = new Dictionary<string, Info<int>>();
In this case I can't add another type of info e.g. Info<double>.
I want something like , I have removed generic version in below case.
{"Price", new Info{Min=100,Max=1000,DefaultValue=200,Step=50}}
{"Adv", new Info{Min=10.50,Max=500.50,DefaultValue=20.50,Step=1.5}}
{"Answer", new Info{Min=false,Max=false,DefaultValue=false,Step=false}}
I can use Dictionary<string, Object> dict = new Dictionary<string, Object>();
but then when I get the dict item back I don't know what type is that, I need to know the type as well e.g. for Price it's int and for Adv it's double , how will I know it at runtime?
Actually I want to create a validator(I am using .Net Compact Framework 3.5/can not use any inbuilt system if it exists) for example If I have a class like below..
class Demo
{
public int Price { get; set; }
public float Adv { get; set; }
public static bool Validate(Demo d)
{
List<string> err = new List<string>();
// here I have to get Info about the Price
// from dictionary, it can be any storage
Info priceInfo = GetPriceInfo("Price");
if (d.Price < priceInfo.Min)
{
d.Price = priceInfo.Min;
err.Add("price is lower than Min Price");
}
if (d.Price > priceInfo.Max)
{
d.Price = priceInfo.Max;
err.Add("price is above than Max Price");
}
// need to do similar for all kinds of properties in the class
}
}
So idea is to store validation information at one place (in dictionary or somewhere else) and then use that info at validation time, I also would like to know if I can design the above scenario in a better way ?
Maybe there is a better way to do this , any guidelines please?
You can use a non-generic base class:
public abstract class Info {
}
public class Info<T> : Info {
}
Now all different generic types inherit from the same base type, so you can use that in the dictionary:
Dictionary<string, Info> dict = new Dictionary<string, Info>();
You can define properties and methods where the interface is not depending on the generic type in the base class, and implement them in the generic class. That way you can use them without specifying the generic type.
For methods where you need the type, you need specific code for each type. You can use the is and as operators to check for a type:
Info<int> info = dict[name] as Info<int>;
if (info != null) {
int max = info.Max;
}
You could take from Microsoft and mimic the IEnumerable interface and create a .Cast<T>? However, somebody is going to have to know about your type unless you want to get into dynamic (4.0+ only) or reflection. Both of which come with a cost. Maybe you need to rethink your design?
Keith Nicholas is right - if you want your dictionary to support multiple types, you'll need an interface, but it will need to be a generic one.
Try something like this (warning: untested code):
interface IInfo<T>
{
T Max { get; set; }
T Min { get; set; }
T DefaultValue { get; set; }
T Step { get; set; }
}
Dictionary<string, IInfo> dict = new Dictionary<string, IInfo>();
class AnswerInfo : IInfo<bool> { }
class PriceInfo : IInfo<int> { }
class AdvInfo : IInfo<double> { }
dict["Answer"] = new AnswerInfo() { Min = false, Max = false, DefaultValue = false, Step = false };
dict["Price"] = new PriceInfo() { Min = 100, Max = 1000, DefaultValue = 200, Step = 50 };
dict["Adv"] = new AdvInfo() { Min = 10.50, Max = 500.50, DefaultValue = 20.50 Step = 1.5 };
Using a Dictionary of objects (or some base class) you would have several options to get to the data (typically, involving some kind of inheritance from a common base class to work with, which has properties as outlined below).
Use an enum to denote the type, then you can have some kind of switch/case. (Easy to do, not very C#ish.)
Use something similar to a VARIANT. Variants are types that provide both information what they store and also the value stored, which can be any base type like string, int, float. (Does not really exist in C#, as you can see from the answers here Variant Type in C# .)
You can also test the type of the object at runtime to find out what kind of an object you have, and then cast it and handle its content depending on its type. (Several ways.. might have to use reflection, for a start have a look here: get object type and assign values accordingly .)
You could actually also try to abstract the operation you want to do on each object in some way, and then call that function. Something like the command pattern. (Command Pattern : How to pass parameters to a command?)
Probably many more. :)
I have these data :
4 pippo pluto paperino
10 marco paolo roberto
2 hello cruel world
and I'd like to store these data into a multi-type matrix myMatrix. (First field is an integer, the rest are strings).
So, if I type myMatrix[1][2] I must get paolo. How can I do it on C#?
Tuple<int, string, string, string>[]
object[][]
Dictionary<int, string[]>
You can't use arrays to store different types of objects that are not part of the same inheritance chain.
an object[][] will work, but you will not have type safety and need to cast to the target type.
You can use Tuple<int,string,string,string>[] (introduced in .NET 4.0), though your own simple type would be a more readable option.
Instead of using arrays, you could use one of the collection types - for example List<T>, where the generic type is a tuple or your custom type.
You really need to think about the usage this collection will be put into before you can select a suitable data structure.
The best way is to create a class that represent your data, with 4 fields (integer, string, string, string).
public class MyClass
{
public int Param1 { get; set; }
public string Param2 { get; set; }
public string Param3 { get; set; }
public string Param4 { get; set; }
}
Then simply use a List<MyClass> to store your data.
To get Paolo you'll need to use List[1].Param2 (also name your parameters with meaningful names).
You can use Dictionary<int, string[]> to get such effect:
Dictionary<int, string[]> myMatrix = new Dictionary<int, string[]>();
myMatrix.Add(4, new[] { "pippo", "pluto", "paperino" });
...
//get
myMatrix[4][1] == "pluto"
Dictionary<int, string[]> is the simplest way as I think.
More about Dictionary type can be found here
I want to store data such as
{
{"apple",15 }
{"pear",12.5 }
{"", 10 }
{"", 0.45 }
}
Data will be plotted on a bar chart (string will be the legend and double will be the value)
Insert order is important.
Perfs don't matter.
Strings could be duplicated or empty. (values could be duplicated too)
I need to get min and max values (easily if possible) to set the scale.
I use
List<KeyValuePair<string, double>> data = new List<KeyValuePair<string, double>>();
data.Add(new KeyValuePair<string,double>("",i));
Quite boring and unreadable.
Is there a cleaner way to do it ?
StringDoubleCollection data = new StringDoubleCollection();
data.add("apple",15);
data.add("",10);
double max = data.values.Max();
double min = data.values.Min();
if not how to get the max value of List<KeyValuePair<string, double>> without too much hassle
NameValueCollection looks nice but its a <string,string> I need a <string,double>
You could create a class like the following:
class X
{
public string Name { get; set; }
public double Value { get; set; }
// name is an optional parameter (this means it can be used only in C# 4)
public X(double value, string name = "")
{
this.Name = name;
this.Value = value;
}
// whatever
}
And then get maximum and minimum values using LINQ with a selector:
var data = new List<X>();
data.Add(new X(35.0, "Apple"))
data.Add(new X(50.0));
double max = data.Max(a => a.Value);
double min = data.Min(a => a.Value);
EDIT: if the code above still seems unreadable to you try to improve it using an operator for cases in which you want to have just the value.
// Inside X class...
public static implicit operator X(double d)
{
return new X(d);
}
// Somewhere else...
data.Add(50.0);
To determine which data structure you really want, lets look at your usage patterns.
Insert order matters.
You don't access your items by key.
You want min and max.
A heap offers min or max, but doesn't preserve order. A hash based dictionary also doesn't preserve order. A List is actually a good choice for your data structure. It is available and offers excellent support.
You can prettify your code by defining classes for both the data structure and your bar data. And you can add min/max functionality to the collection. Note: I didn't use the Linq Min/Max functions, because they return the minimum value, not the minimum element.
public class BarGraphData {
public string Legend { get; set; }
public double Value { get; set; }
}
public class BarGraphDataCollection : List<BarGraphData> {
// add necessary constructors, if any
public BarGraphData Min() {
BarGraphData min = null;
// finds the minmum item
// prefers the item with the lowest index
foreach (BarGraphData item in this) {
if ( min == null )
min = item;
else if ( item.Value < min.Value )
min = item;
}
if ( min == null )
throw new InvalidOperationException("The list is empty.");
return min;
}
public BarGraphData Max() {
// similar implementation as Min
}
}
Have you looked at LookUp?
The only problem is that it's immutable, so you need to be able to create your collection in one go.
As Anthony Pegram notes, it's a bit of a pain to create one. It depends on where your data is coming from. Have a look at the ToLookup method.
If it's worth it for usability (i.e. you're using awkward collections of List<KeyValuePair<string, double>> everywhere, it might just be worth it to implement StringDoubleCollection. It wouldn't be that difficult to wrap the underlying collection with the friendlier syntax you've described in your example.
And, as other comments / answers are suggesting, the Framework doesn't seem to provide a simpler solution that matches all of your requirements...
As for "max value", I assume you mean the Key-Value Pair with the greatest value. It can be retrieved like so:
var max = list.Select(kvp => kvp.Value).Max();
Just define your own model class to hold the data instead of depending on a KeyValuePair and everything becomes cleaner:
using System;
using System.Collections.Generic;
public class Fruit
{
public string Name {get; set;}
public double Price {get; set;}
}
public class Program
{
public static void Main()
{
List<Fruit> _myFruit = new List<Fruit>();
_myFruit.Add(new Fruit{Name="apple", Price=15 });
_myFruit.Add(new Fruit{Name="pear", Price=12.5 });
_myFruit.Add(new Fruit{Name="", Price=10 });
_myFruit.Add(new Fruit{Name="", Price=0.45 });
// etc...
}
}
What about implementing the StringDoubleCollection to work like you want...
public class StringDoubleCollection
{
private List<KeyValuePair<string, double>> myValues;
public List<double> values
{
get { return myValues.Select(keyValuePair => keyValuePair.Value).ToList(); }
}
public void add(string key, double value)
{
myValues.Add(new KeyValuePair<string,double>(key,value));
}
}
You can implementing Dictionary<key, value>
Dictionary<string, string> openWith = new Dictionary<string, string>();
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe");
https://learn.microsoft.com/pt-br/dotnet/api/system.collections.generic.dictionary-2?view=net-5.0