List<> with numbers and text - c#

Is there a List<> similar to a two dimension array? For each entry there is a number and text.

You can use Dictionary<int,String>
Sample:
Dictionary<int,string> samp = new Dictionary<int,string>();
dictionary.Add(1, "text1");
dictionary.Add(2, "text2");
Or, have a custom class which defines your requirement
public class Sample
{
public int Number;
public string Text;
}
Sample:
List<Sample> req = new List<Sample>();
Sample samObj = new Sample();
samObj.Number = 1;
samObj.Text = "FirstText";
req.Add(samObj);

There are many options, I describe some of them for you
use Dictionary<int, string>
Pros: very fast lookup
Cons: you can not have two string with same number, you don't have a List
var list2d = new Dictionary<int, string>();
list2d[1] = "hello";
list2d[2] = "world!";
foreach (var item in list2d)
{
Console.WriteLine(string.Format("{0}: {1}", item.Key, item.Value);
}
use Tuple<int, string>
Pros: very simple and handy tool, you have a List
Cons: Tuples are immutable, you can not change their values once you create them, reduces code readability (Item1, Item2)
var list2d = new List<Tuple<int, string>>();
list2d.Add(new Tuple(1, "hello"));
list2d.Add(Tuple.Create(1, "world");
foreach (var item in list2d)
{
Console.WriteLine(string.Format("{0}: {1}", item.Item1, item.Item2);
}
use a defined class,
Pros: you have a List, very customizable
Cons: you should write more code to setup
public class MyClass
{
public int Number { get; set; }
public string Text { get; set; }
}
var list2d = new List<MyClass>();
list2d.Add(new MyClass() { Number = 1, Text = "hello" });
list2d.Add(new MyClass { Number = 2, Text = "world" });
foreach (var item in list2d)
{
Console.WriteLine(string.Format("{0}: {1}", item.Number, item.Text);
}

Custom class or dictionary are good options, you can also use the Tuple generic...
var i = new List<Tuple<int, string>>();
Dictionary requires that whatever value is used as key must be unique. So not ideal without uniqueness.
A custom class is preferable if you don't mind a little more code and gives you scope to extend later on if you decide you want other data in there.
Tuple is quick and easy but you lose readability and objects can not be edited.

Define a class wih a string and an int property
public class MyClass
{
public string MyStr {get;set;}
public int MyInt {get;set;}
}
then create a list of this class
List<Myclass> myList = new List<MyClass>();
myList.add(new MyClass{MyStr = "this is a string", MyInt=5});

Hope it will help
public class DATA
{
public int number;
public string text;
}
List<DATA> list = new List<DATA>();

Related

How to address specific element in list

I want to create "list of list of list". It should be:
Group (has a list of Members)
Member (has a Name and list of Properties)
Property (has Name and Value)
What I want is to have a possibility to add Property into Member (specified by its name) inside defined Group. Someting like this:
membersgroup.AddNewMember(memberXYZ);
...
membersgroup.memberXYZ.AddProperty(nameXYZ, valueXYZ).
I have trouble achieving this using list... I found class Hashable, but I am not sure if this is usable... and cannot make it works too...
Thank for any suggestion :)
Well, I suggest you create a custom class instead of your approach. But otherwise you can use a Dictionary.
var properties = new Dictionary<string, string>();
properties.Add("Prop1", "Value");
var members = new Dictionary<string, Dictionary<string, string>>();
members.Add("Member1", properties);
var group = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
group.Add("GroupName", members);
public class Group
{
public Group()
{
Members = new List<Member>();
}
public IEnumerable<Member> Members { get; set; }
}
public class Member
{
public Member()
{
Properties = new Dictionary<string, string>();
}
public string Name { get; set; }
IDictionary<string, string> Properties { get; set; }
}
The dictionary can take a key and a value, and the key should be unique.
You can also create a class property if you want to add another thing beside the name and the value
I would use indexers.
Here's a partial implementation:
class Group
{
private List<Member> _members;
public string this
{
get
{
return _members.Find(m => m.Name == value);
}
// You can also implement set here if you want...
}
}
class Member
{
private List<Property> _properties;
public string Name {get;set;}
public string this
{
get
{
return _properties.Find(m => m.Name == value);
}
}
}
class Property
{
public string Name {get;set;}
public string Value {get;set;}
}
And the usage:
var g = new Group();
g[memberName][propertyName].Value = someValue;
Note: This implementation is partial! it still needs constructor logic and any other logic you might need.
Likely the best solution is to use the C# class Dictionary - as suggested by zetawars, or a custom class - as suggested by Zohar Peled, or some mix of the two - as suggested by gandalf.
However, in order to use syntax similar to what is requested in the question...
membersgroup.AddNewMember(memberXYZ);
...
membersgroup.memberXYZ.AddProperty(nameXYZ, valueXYZ).
You can abuse ExpandoObject and Action, and do something awesome like this:
dynamic membersgroup = new ExpandoObject();
var getNewMemberObject = new Func<dynamic>(() =>
{
dynamic memberObject = new ExpandoObject();
var addPropertyAction = new Action<string, string>((propertyName, propertyValue) =>
{
((IDictionary<string, object>)memberObject).Add(propertyName, propertyValue);
});
memberObject.AddProperty = addPropertyAction;
return memberObject;
});
var addNewMemberAction = new Action<string>((memberName) =>
{
((IDictionary<string, object>)membersgroup).Add(memberName, getNewMemberObject());
});
membersgroup.AddNewMember = addNewMemberAction;
string memberXYZ = nameof(memberXYZ);
string nameXYZ = nameof(nameXYZ);
string valueXYZ = nameof(valueXYZ);
// look we did it!
membersgroup.AddNewMember(memberXYZ);
membersgroup.memberXYZ.AddProperty(nameXYZ, valueXYZ);
// and it actually works
var actualValue = membersgroup.memberXYZ.nameXYZ;
Console.WriteLine(actualValue); // "valueXYZ"
(for science of course)

Class to return different types - best option?

I need a class that can work with string properties to store data on a structured (class) list but at the same type to have a way to return an index that acts as the order I need to set up my data.
the class can be something like:
public class MyClass
{
public int int1 = 0;
public int int2 = 0;
public int int3 = 0;
public int int4 = 0;
public string string1 { get; set; }
public string string2 { get; set; }
public string string3 { get; set; }
public string string4 { get; set; }
}
then I can use my class to store the data in the class structured format:
string fileName = #"C:\Mylocation\MyTextFileToRead.txt"; //tab delimeted file
Encoding fileEncoding = Encoding.ASCII;
List<MyClass> myDataList = new List<MyClass>();
List<string> simpleData = File.ReadAllLines(fileName, fileEncoding).ToList();
MyClass index = new MyClass();
foreach (var line in simpleData)
{
var lineSplit = line.Split('\t');
MyClass myClassElement = new MyClass
{
string1 = lineSplit[index.int1],
string2 = lineSplit[index.int2],
string3 = lineSplit[index.int3],
string4 = lineSplit[index.int4],
};
myDataList.Add(myClassElement);
}
I use the index to map each property from the text file and then to store each filed values in the corresponding string property.
I do not wish to use object types and have the properties to return a string value and cast it as (int) for the index. I was advised not to use objects as much as possible.
The use of Const fields did not work for the index unless I use the type name of the class (instead an instance of the class), but I don't know if it helps or if this is a better programming option.
I'm not sure if there is a better way of doing this, but would be very welcome with relevant feedback.
To return two diffrent types from one function you can use the way that was introduce in C# 7.3
It works like this:
public (int, string) MyFunc()
{
//do something
return (VarThatInt, VarThatString);
}
//and in main class u call it like this:
(varInt, varString) = MyFunc();
using KeyValuePair to store one property and index, use list of KeyValuePair to store one line , and use dic Dictionary to store file .
List<int> orderIndexList = new List<int> { 2, 1, 4, 0 };
Dictionary<int, List<KeyValuePair<int, string>>> data = new Dictionary<int, List<KeyValuePair<int, string>>>();
int lineNumber = 0;
foreach (var line in simpleData)
{
var lineSplit = line.Split('\t');
List<KeyValuePair<int, string>> listLine = new List<KeyValuePair<int, string>>();
orderIndexList.ForEach(index => listLine.Add(new KeyValuePair<int, string>(index, lineSplit[index])));
data.Add(++lineNumber, listLine);
}
return data;
Return a class that has the two desired outputs. You can even return a third variable to tell the receiving code, which output to use.
public myClass{
String TextValue;
int NumberValue;
bool IsReturnString;
}
You would return an object of myClass.

Define list of objects. Get by specific field in object

How can we create a list of objects in C# and acces them by a specific field inside this object?
For example take this object:
class Section
{
public string Name { get; }
public long Size { get; }
public Section(string name, long size)
{
Name = name;
Size = size;
}
}
I would like to create a list of these objects which I can access by Section.Name.
I can create a dictionary like:
private static readonly Dictionary<string, Section> validSections = new Dictionary<string, Section>
{
{ "section-a", new Section("section-a", 1) },
{ "section-b", new Section("section-b", 2) },
{ "section-c", new Section("section-c", 3) },
{ "section-d", new Section("section-d", 4) },
};
But as you see, I have to declare the section name twice, which looks inelegant. Is there a more elegant way?
But as you see, I have to declare the section name twice, which looks
inelegant. Is there a more elegant way?
To avoid repetitve typing you can create dictionary from collection of sections via ToDictionary call:
private static readonly Dictionary<string, Section> validSections = new[] {
new Section("section-a", 1),
new Section("section-b", 2),
new Section("section-c", 3),
new Section("section-d", 4)
}.ToDictionary(s => s.Name);
If this is not time critical then you can use List<Section> list = new ArrayList<Section>(); and store data in it.
Later you can use LINQ to query based on name .where(x=>x.Name=="somename")
First of all your Model class can look like:
class Section
{
public string Name { get; set; }
public long Size { get; set; }
}
You don't need the Name twice so you can just create a list:
private static List<Section> myList = new List<Section>();
myList.add(new Section {Name = "section-a", Size = 1});
// do this for all the sections ...
Then as other answers suggest you can use LINQ:
myList.Single(s => s.Name == "section-a");
Will simply return the single element where the name is "section-a".
Read more about LINQ here: https://msdn.microsoft.com/en-us/library/bb308959.aspx
You could write a function that takes a list of sections and returns the corresponding dictionary. Something like:
public static Dictionary<string, Section> SectionDictionary(List<Section> sections) {
var dict = new Dictionary<string, Section>();
foreach (var section in sections)
dict.Add(section.Name, section);
return dict;
}
You can just access the elements using LINQ:
var list = ...;
var el = list.FirstOrDefault(o => o.Name = nameValue);
Or you can create a (collection) class that implements your own indexer / getter logic. E.g. (pseudocode)
public class MyCollection : Collection<Section>
{
public Section this[string nameValue]
{
get
{
return this.FirstOrDefault(o => o.Name == nameValue);
}
}
}
Then the usage is:
var coll = new MyCollection() ....;
var el = coll["Some name"];

ArrayList with Multiple Values c#

I am unsure whether this is possible with an ArrayList or a Dictionary or whether it would be something else, if so I wonder where you could point me in the right direction...
Can you have an ArrayList with Multiple Values i.e.
ArrayList weather = new ArrayList();
weather.Add("Sunny", "img/sunny.jpg");
weather.Add("Rain", "img/Rain.jpg);
To then assign to controls like below.
if (WeatherValue = 0)
{
Label1.Text = weather[0].ToString;
Image1.ImageUrl = weather[0].ToString;
}
Or can I do this with a Dictionary
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("Cloudy", "../img/icons/w0.png"); //[0]
dict.Add("Rain", "../img/icons/w1.png"); //[1]
Label1.Text = dict[0].VALUE1; //So this would get Cloudy
Image.ImageUrl = dict[0].VALUE2; //This would get ../img/w0.png
How do you call the values of a dictionary separately using [0], and [1] ? etc
There's no reason to still use ArrayList, use the System.Collections.Generic.List<T>-class. Then you keep compile time safety and you don't need to cast everything.
In this case you should create a custom class:
public class Weather
{
public double Degree { get; set; }
public string Name { get; set; }
public string IconPath { get; set; }
public override string ToString()
{
return Name;
}
}
Then you can use this readable and maintainable code:
List<Weather> weatherList = new List<Weather>();
weatherList.Add(new Weather { Name = "Sunny", IconPath = "img/sunny.jpg" });
weatherList.Add(new Weather { Name = "Rain", IconPath = "img/Rain.jpg" });
if (WeatherValue == 0) // whatever that is
{
Label1.Text = weatherList[0].Name;
Image1.ImageUrl = weatherList[0].IconPath;
}
Update: according to your edited question. A dictionary doesn't make much sense because you can't access it via index(it has no order) but only via key. Since that would be the weather-name you have to know it beforehand. But it seems that you don't have it.
So either loop all key-value pairs in the dictionary and use the key for the name and the value for the path or simply use a real class which would be much better.
If you don't want to create a class there's only one thing that comes to my mind, the Tuple:
List<Tuple<string, string>> weatherList = new List<string, string>();
weatherList.Add(Tuple.Create("Sunny", "img/sunny.jpg"));
weatherList.Add(Tuple.Create("Rain", "img/Rain.jpg"));
if (WeatherValue == 0) // whatever that is
{
Label1.Text = weatherList[0].Item1;
Image1.ImageUrl = weatherList[0].Item2;
}
You can use a Dictionary
Dictionary<string, string> weather = new Dictionary<string, string>();
values.Add("Sunny", "img/sunny.jpg");
values.Add("Rain", "img/Rain.jpg");
The simplest way to call element in a dictionnary is using foreach loop
foreach (var pair in weather )
{
Console.WriteLine("{0}, {1}",pair.Key,pair.Value);
}

Storing 2 columns into a List

How can I store data from 2 columns (from a database) in a List
List<string> _items = new List<string>();
Any help is appreciated
You create a class that will represent a row with 2 columns:
public class Foo
{
// obviously you find meaningful names of the 2 properties
public string Column1 { get; set; }
public string Column2 { get; set; }
}
and then you store in a List<Foo>:
List<Foo> _items = new List<Foo>();
_items.Add(new Foo { Column1 = "bar", Column2 = "baz" });
Use a tuple struct like KeyValuePair
List<KeyValuePair<string, string>> _items = new List<KeyValuePair<string, string>>();
_items.Add(new KeyValuePair<string, string>(foo, bar));
I would use a class
List<MyDataClass> _items = new List<MyDataClass>();
public class MyDataClass
{
public string Value1 { get; set; }
public string Value2 { get; set; }
}
You can either create a new class to hold the data, Or you could use the built in Tuple<> class. http://msdn.microsoft.com/en-us/library/system.tuple.aspx
Also if one of the columns contains a unique ID of some sort, you could also consider using a Dictionary<>.
It's about how to retrieve the data from the new two columns list
List<ListTwoColumns> JobIDAndJobName = new List<ListTwoColumns>();
for (int index = 0; index < JobIDAndJobName.Count;index++)
{
ListTwoColumns List = JobIDAndJobName[index];
if (List.Text == this.cbJob.Text)
{
JobID = List.ID;
}
}
I know this question is pretty old and by now you probably got your answer and have figured out what you need but I wanted to add something that might help someone in the future.
The best current answer is frankly from #csharptest.net but it has a serious performance drawback and so here is my approach a la his answer based on a suggestion to use Dictionary<TKey, TValue>
private Dictionary<string, string> _items = new Dictionary<string, string>();
// if you need to check to see if it exists already or not
private void AddToList(string one, string two)
{
if (!_items.ContainsKey(one))
_items.Add(one, two);
}
// you can simplify the add further
private void AddToList(string one, string two)
{
_items[one] = two;
// note if you try to add and it exists, it will throw exception,
// so alternatively you can wrap it in try/catch - dealer's choice
}
you can also make array of list
List<string> [] list= new List<String> [];
list[0]=new List<string>();
list[1]=new List<string>();
list[0].add("hello");
list[1].add("world");
You could do this:
List<IList<string>> cols = new List<IList<string>>();
You can set how many columns you want.
cols.Add(new List<string> { "", "", "","more","more","more","more","..." });

Categories