c# a collection to hold two arraylist - c#

I am using C#.
I've created 2 arraylists called Names and Performances and the data in them are filled from my database.
I wanna create an arraylist or something like an array of 2 dimensions so
array[Name][Performance].
array[0][0] => should give me first persons first performance data
array[0][1] => should give me firstpersons second performance data
array[0][2] => should give me first persons third performance data...
The size of Names and Performance are changeable due to diffrent sql queries.
since sizes are changeable i tried to use loops and size of Name and Performance arraylists in those loops. How can i handle that collection to hold both of my arraylists?

Why don't you use a generic List ?
You can then for instance create a type which holds the Person and his performance data, like this:
class PersonPerformance
{
public string Name { get; set; }
public List<Performance> Performances { get; set; }
}
And you create a collection easily:
var performances = new List<PersonPerformance>();

You can use something like that
IList<KeyValuePair<string, string>> innerList = new List<KeyValuePair<string, string>>();
IList<IList<KeyValuePair<String,string>>> list=new List<IList<KeyValuePair<string, string>>>();
list.Add(innerList);
Where KeyValuePair contains Name and Perfomance element

I assume your Names are of the type string.
I usually do (if I don't have set size)
List<KeyValuePair<string, TYPE_X>> list = new List<KeyValuePair<string, TYPE_X>>();
or (the size is known)
KeyValuePair<string, TYPE_X>[] array = new KeyValuePair<string, TYPE_X>[size];
or better
public Dictionary<string, TYPE_X> dict = new Dictionary<string, TYPE>();
if names are unique and I want to acces them like that (not in order):
TYPE_X object = dict["myName"];

You can use Use Dictionary<Name,List<Performance>> Type
hence for each name you get the set of Performances

Related

C# List or Array with String and Number

What is the best method to create an array or a list which contain a string and a number?
With Dictionary it can be done this way:
Dictionary < string, int > dict = new Dictionary < string, int > ();
but are there better methods with Array or List?
I need it to store IP addresses and coresponding port numbers.
The best way depends on your use case. But here's an easy way.
var list = new List<Tuple<string, int>> {
Tuple.Create("foo", 123),
Tuple.Create("bar", 234),
};
If you want a list of correlated ip addresses and ports, I'd make a dedicated type for it.
struct Address {
public string Ip;
public int Port;
}
...
var list = new List<Address>();
Due to the hashtable it is built upon; a Dictionary is the faster way to go if you are going to search the content to find a certain key.
var list = new Dictionary<string, int>();
A List of Key/Value pairs would need to parse each entry, every single "KeyValuePair" that is, to check if it contains a specific key. This will lead to an slightly exponentional performance loss upon adding more and more entries.
var list = new List<KeyValuePair<string, int>>();

Information Storage for 3 variables

I am trying to create a good way to store 3 variables, two ints and a point in C# programming.
I thought of a way by using an array of dictionaries
Dictionary<int, Point>[] ItemList = new Dictionary<int, Point>[4];
The Idea was that one variable has to be between 1 and 4, so I would have that as the sorting point, or each array location. The 2nd int, has to be between 0 and 15, and the point is on a 4x4 grid. I thought this method would work, and it would have except that You can't have the same key in a dictionary, and since both ints will be repeated, I can't swap them out. This idea also went out the window, same problem
Dictionary<int, int>[,] ItemList = new Dictionary<int, int>[4,4];
I also thought of using a tuple, and I don't have much(any) experience with it, and my experiments with them weren't going so well. The problem with it was I couldn't get the count of how many items were in it. I set one up like this.
Tuple<int, Point>[] ItemList = new Tuple<int, Point>[4];
Same Idea as my first example, Its just there is no code like this
ItemList[1].Count /*OR*/ ItemList[1].Length
Please let me know if I am missing something terribly obvious with tuples, or suggest an different storage method that would be nice to have all 3 variables stored all together.
You can use the Tuple to store directly the 3 data structures. A Tuple can have more than two items, and of any type. That way, you don't have to use your array:
Tuple<int, int, Point>
To get the values, use the corresponding Item property. For the first int, it will be yourTuple.Item1. For the second one yourTuple.Item2 and for the Point yourTuple.Item3.
If you have multiple Tuples, you can use a classic List to store them all:
var tuples = new List<Tuple<int, int, Point>>();
Since it's a list, you can get the count easily: tuples.Count()
So a class seems like the proper structure to me.
public class Something {
public int Item1 { get; set; }
public int Item2 { get; set; }
public Point Location { get; set; }
}
Then you store these objects in a List<>
var List<Something> list = new List<Something>();
add items to the list...
list.Add(new Something() {Item1 = 4, Item2 = 8, Point = new Point(x,y)});
then use some LINQ to get just the ones you want.
var onlyItem1IsFour = (from item in list where 4 == item.Item1 select item).ToList();
excuse my LINQ. I'm used to VB and may have gotten the casing/syntax slightly wrong
Well, Using the idea of using a list, I solved my problem. Its kinda a hybrid between the suggested ideas and my original idea with using the array. You don't have to use an array if you are looking to do something similar, you can use a tuple with 3 values, I just needed an array for one int value because I needed them stored separately, based off of what that one int value was (between 0 and 4). Here is some code that would work.
List<Tuple<int, Point>>[] ItemList = new List<Tuple<int, Point>>[4]; // how to declare it
for (int i = 0; i < 4; i++)
{
ItemList[i] = new List<Tuple<int, Point>>(); // initilize each list
}
ItemList[1].Add(new Tuple<int, Point>(5, new Point(1, 2))); // add a new tuple to a specific array level
int count = ItemList[1].Count; // finds the count for a specific level of the array --> (1)
int getInt = ItemList[1].ElementAt(0).Item1; // finds int value --> (5)
Point getPoint = ItemList[1].ElementAt(0).Item2; // finds the point --> (1,2)

increasing dimensions in a list

using ...
string[] myFiles = Directory.GetFiles(FilePathIn, "*.dat", SearchOption.TopDirectoryOnly);
I am getting a list of files returned. Alongside this I want to keep a set of int flags. I am about to do this by creating a tuple list eg List<Tuple<int, string>> then looping through myfiles adding each to the tuple list.
Although this will work I wondered if there was a cleaner way to do this? It doesn't have to be a tuple list. It just needs to be an ordered list of the files with a flag
If you are interested in just iteration then a list of some compound type is the way to go -- you can use a custom struct instead of a Tuple to increase readability or a custom class if you intend for the flags to be mutable later on, but the general idea is the same.
You can also use a Dictionary<string, int> of filenames to flags; this has the advantage that it allows quick lookups if you have a filename in hand.
Finally, consider using a [Flags] enum instead of a bare integer to hold the flags you need.
Depending on how you want to use the data later, I would either map the filenames to the integers (Dictionary<string, int>) or the integers to files. I assume two files can have the same "flag", so I would use either a Dictionary<int, List<string>> or constuct IGrouping<int, string> or ILookup<int, string>. It's a shame really that .NET BCL doesn't contain a straightforward mutable Multimap (or Lookup) that you could use like a dictionary.
Why you don't use dictionary to access an element in a dictionary it will cost O(1)
Dictionary<int,string> myFilesOrderedDict = new Dictionary<int,string>();
Or if you want to groupfile by an int as a flag you can do the inverse as I don't think that the name of the file can be repeated twice
Something like this
//string will be the name of the file
Dictionary<string ,int> myFilesOrderedDict = new Dictionary<string,int>();
Hope this help
You can create an anonymous type:
var filesWithFlags = Directory.GetFiles(..)
.Select(f => new {File = f, Flags = 123});
And use the result like this:
foreach (var fileWithFlags in filesWithFlags)
{
DoSomethingWith(fileWithFlags.File);
AndDoSomethingWith(fileWithFlags.Flags);
}

Is there something like the .NET Dictionary with duplicated keys to fill with a text file?

I have a text file with the following structure
01|value|value|value|value|value|value
02|value|value|value|value|value|value
03A|value|value|value|value|value|value
03A|value|value|value|value|value|value
.
.
N
04|value|value|value|value|value|value
05|value|value|value|value|value|value
06|value|value|value|value|value|value
.
.
N (variable lines)
I tried to read the text file and add it to a dictionary of type <string, string[]> in order to use it like MyDic["01"][0], this is a fragment of the code:
Dictionary<string, string[]> txtFromFile= new Dictionary<string, string[]>();
string strLine;
using (StreamReader sr = new StreamReader(filePath))
{
while ((strLine= sr.ReadLine()) != null)
{
string[] strNodes= strLine.Split('|');
txtFromFile.Add(strNodes[0], strNodes);
}
}
Unfortunately, as you can see, this text file could have duplicated keys like 03A, so I was wondering if there's a collection in c# to achieve this.
NOTE I saw a class named lookup, but there's no constructor for it.
Any thoughts my friends?
What do you suggest?
Thanks!
Why not just create a class like
public class MyLine
{
string key { get;set;}
string[] value {get;set;}
}
and store it in a geneirc List
then you can use linq to query whatever you want ...
You can use the ToLookup extension method:
string[] lines = File.ReadAllLines(filePath);
ILookup<string, string[]> result = lines
.Select(line => line.Split('|'))
.ToLookup(parts => parts[0]);
The first problem is that you are trying to use the wrong type, if you are concerned with multiple entries with the same key. You can achieve this with a List<KeyValuePair<string, string[]>> and your own lookup function, likely through extending the class, or you can add another dictionary inside the dictionary as your value type: Dictionary<string, Dictionary<int, string[]>>. The Dictionary option is the better bet as it has better performance.
How about a List with a custom type?
class KeyValue
{
String ID { get ; set ; }
List<String> Values { get ; private set ;}
(..Constructor etc...)
}
List<KeyValue> myValues = new List<KeyValue>();
while ((strLine= sr.ReadLine()) != null)
{
string[] strNodes= strLine.Split('|');
myValues.Add(new KeyValue(strNodes[0],strNodes));
}
You could use List<KeyValuePair<string, string[]>> or List<Tuple<string, string[]>>
(And of course you might prefer a different collection type instead of List<>)
I'm not sure if you're trying to distinguish between values on the first 03A line from values on the second 03A line, but I think you're looking for a NameValueCollection. NameValueCollections allow you to add multiple values to the same key, and the Add() method should check for pre-existing keys before appending the values/creating a new key/value entry.
There's a good example of the way to use the NameValueCollection at the bottom of that MSDN reference article, so you should be able to use that to determine if it's what you really need.
Another thought would be to use
Dictionary<string, List<string[]>>
Where "string" is the value that might be repeated. When it gets repeated, you create another Dictionary inside. If a row exists once, it will have one List. If a duplicate row is found, add another. In this way, you can see how many duplicate rows there were just by count of Lists.

Store Collection of Data Fields and Retrieve Via Identifier

In C#, how can I store a collection of values so if I want to retrieve a particular value later, I can do something like:
myCollection["Area1"].AreaCount = 50;
or
count = myCollection["Area1"].AreaCount;
Generic list?
I'd like to store more than one property to a "key". Is a class the answer?
You're looking for the Dictionary<string, YourClass> class. (Where YourClass has an AreaCount property)
EDIT
Based on your comment, it seems like you want a Dictionary (as already suggested) where your object holds all your 'values.'
For Instance:
public class MyClass
{
public int AreaCount;
public string foo;
public bool bar;
}
//Create dictionary to hold, and a loop to make, objects:
Dictionary<string, MyClass> myDict = new Dictionary<string, MyClass>();
while(condition)
{
string name = getName(); //To generate the string keys you want
MyClass mC = new MyClass();
myDict.Add(name, mC);
}
//pull out yours and modify AreaCount
myDict["Area1"].Value.AreaCount = 50;
Alternatively, you could add a string "Name" to you class (I'm using fields for the example, you'd probably use properties) and use Linq:
//Now we have a list just of your class (assume we've already got it)
myClass instanceToChange = (from items in myList
where Name == "Area1"
select item).FirstOrDefault();
myClass.AreaCount = 50;
Does that help more?
ORIGINAL RESPONSE
I'm not completely sure what you're asking, but I'll give it ago.
Given a list of Objects from which you need to grab a particular object, there are (generally) 4 ways- depending on your specific needs.
The Generic List<T> really only does this well at all if your object already supports some kind of searching (like String.Contains()).
A SortedList uses IComparer to compare and sort the Key values and arrange the list that way.
A Dictionary stores a Key and Value so that KeyValuePair objects can be retrieved.
A HashTable uses Keys and Values where the Keys must implement GetHashCode() and ObjectEquals
The specific one you need will vary based on your specific requirements.
This functionality is provided by indexers

Categories