Convert arraylist to a list of dictionaries? - c#

Does somebody know how to convert an arraylist to a list of dictionaries?
What do I have? I have an ArrayList (list) with a lot of strings:
foreach (string s in list)
{
Console.WriteLine(s);
}
output:
klaus
male
spain
lissy
female
england
peter
male
usa
...
As we see there is an order. The first entry is a NAME, second GENDER, third COUNTRY and then again NAME, GENDER... and so on.
Now for clarity I would like to store these attributes in a List of Dictionaries. Every List entry should be 1 Dictionary with these 3 Attributes. Is this a good idea? Whats the easiest way? I just search something to store this list in a better looking collection that is later easiert to handle. I have this:
List<Dictionary<string, string>> dlist = new List<Dictionary<string, string>>();
const int separate = 3;
foreach (string s in list)
{
//add list entries to dlist?
}

No it's not a good idea. Define a class.
At least something like this:
class Person
{
public string Name { get; set; }
public string Gender { get; set; }
public string Country { get; set; }
}
Even better would be to use an enum for Gender, and possibly a class (built-in or custom) for the country.
Anyway, to populate a collection with the above class, you'd use something like:
List<Person> result = new List<Person>();
for (int i = 0; i < list.Count; i += 3) {
result.Add(
new Person { Name = list[i], Gender = list[i+1], Country = list[i+2] });
}
Note that this loop lacks error checking on the count of items in the list, which should be a multiple of three.

enum Gender
{
Male = 0,
Female = 1
}
class Person
{
public string Name { get; set; }
public Gender Gender { get; set; }
public string Country { get; set; }
public Person(string name, Gender gender, string country)
{
this.Name = name;
this.Gender = gender;
this.Country = country;
}
}
Usage:
List<Person> persons = new List<Person>();
Person person;
for (int i = 0; i < list.Count; i += 3) {
{
person = new Person(list[i], (Gender)Enum.Parse(typeof(Gender), list[i+1], true), list[i+2]);
persons.add(person);
}

I would recommend using a class to encapsulate your entry:
class Entry
{
public String Name { get; set; }
public String Gender { get; set; }
public String Country { get; set; }
}
Then add to a list of Entrys
List<Entry> elist = new List<Entry>();
for (int i = 0; i < list.Count; i += 3)
{
var ent = new Entry() { Name = list[i],
Gender = list[i+1],
Country = list[i+2]};
elist.Add(ent);
}
Or you could use Tuples:
List<Tuple<string, string, string>> tlist =
new List<Tuple<string, string, string>>();
for (int i = 0; i < list.Count; i += 3)
{
Tuple<string,string, string> ent
= new Tuple<string,string,string>(list[i], list[i+1], list[i+2]);
tlist.Add(ent);
}

the simplest way to implement that - it's create a new class for representing someone in you list with 3 props:
public class Someone {
public string Name { get; set; }
public string Gender { get; set; }
public string Country { get; set; }
}
And than you can fill your destination list with Someone entries:
List<Someone> dList = new List<Someone>();
for(int i = 0; i < list.Count; i += 3)
dList.Add(new Someone() { Name = list[i], Gender = list[i+1], Country = list[i+2] });
p.s. this code may contain errors because I don't have access to computer with VS installed.

You may have a class to hold the data like:
public class Info
{
public string Name { get; set; }
public string Gender { get; set; }
public string Country { get; set; }
}
then you can have a dictionary like this
Dictionary<int, Info> infoDict = new Dictionary<int, Info>();
then you can start reading and prepare the dictionary.

var listSrc = new List<string>
{
"klaus",
"male",
"spain",
"lissy",
"england",
"female",
"peter",
"usa",
"male",
};
var dlist = new List<Dictionary<string, string>>();
for (var i = 0; i < listSrc.Count; i++)
{
var captions = new List<string>
{
"Name",
"Gender",
"Country"
};
var list = listSrc.Take(3).ToList();
listSrc.RemoveRange(0, 3);
dlist.Add(list.ToDictionary(x => captions[list.IndexOf(x)], x => x));
}

Its simple. You are working for a class that contains three data variables named :
String name;
String gender;
String country;
So make a class that contains all three of these variables. As for eg:
class Dictnary
{
public Dictnary(String nameFromCall, String genderFromCall, String countryFromCall)
{
this.name = nameFromCall;
this.gender = genderFromCall;
this.country = countryFromCall;
}
}

To answer the question in the title, this is probably the most succinct way to do the conversion:
for (int i = 0; i < list.Count; i += 3) {
dlist.Add(new Dictionary<string, string>() {
{ "name", (string)list[i] },
{ "gender", (string)list[i+1] },
{ "country", (string)list[i+2] }
});
}
(If you switch from an ArrayList to a List<string>, you can drop the (string) cast.)
That said, unless you really need a dictionary for some technical reason, your problem is better solved using one of the class-based approaches suggested in the other answers.

Related

Update Objects LIst<T> With Multiple Items

I can update a List using "single line" updates, but I'd like to update multiple items on a single line, similar to the way the List is initialized.
Here is my code:
public class Players
{
public int id;
public string Rank = "";
public string PlayerName = "";
public string LName = "";
public string FName = "";
public string Team = "";
}
List<Players> newList = new List<Players>();
newList.Add(new Players() { id = 111, PlayerName = "Alpha" });
newList.Add(new Players() { id = 222, PlayerName = "Beta" });
newList.Add(new Players() { id = 333, PlayerName = "Gamma" });
newList[0].FName = "Joe";
newList[0].LName = "Smith";
newList[0].Team = "Yankees";
// newList[1] ={ FName="Babe" , Lname="Ruth", Team="Boston"};
foreach(var item in newList)
{
Console.WriteLine(item.id+" "+item.PlayerName+" "+item.FName+" "+item.LName+" "+item.Team);
}
I want to use something like below to update the list object with multiple items with one line. But this line throws and exception "FName does not exist in current context"
This is the error line // newList[1] ={ FName="Babe" , Lname="Ruth", Team="Boston"};
How do I create/format the correct way to update a List object?
If you want to set those three properties with a one liner, why not implementing a method in the Player class?
public class Player {
//...
public void SetProperties(string Fname, string Lname, string team)
{
FName = fName,
LName = lName,
Team = team
}
}
Then you can do
var newList = new List<Player>();
//...
newList[0].SetProperties("Babe", "Ruth", "Boston");
Edit: #godot suggested that is better to have a method to update just some properties of the Player object. A way to achieve this goal is reflection and anonymous types.
I propose a refactoring of the SetProperties method:
public class Player
{
public int Id { get; set; }
public string Rank { get; set; }
public string PlayerName { get; set; }
public string LName { get; set; }
public string FName { get; set; }
public string Team { get; set; }
public void SetProperties(object obj)
{
foreach (var prop in obj.GetType().GetProperties())
{
var propertyToUpdate = this.GetType().GetProperty(prop.Name);
if(propertyToUpdate != null) propertyToUpdate.SetValue(this, prop.GetValue(obj));
}
}
By implementing this method you can update your list object like this:
newList[0].SetProperties( new { FName = "Babe", LName = "Ruth", Team = "Boston" } );
You can create/format the entire player by creating a new player and overwriting everything.
newList[1] = new Players() { FName="Babe" , Lname="Ruth", Team="Boston"};

What is the best way to display List items on the console based on the value of the items' properties?

I have a List that cointains some objects that have 2 string and 2 int properties. I would like to be able to display all the 4 properties of an object based on the content of its first property.
For example: I want to display all the data of all the items of the list that's first property is "Mozart".
Thanks in advance!
I have a really basic class that has 4 properties, 2 strings, and 2 ints, all of them have their respective getters/ setters set to public.
I also have a List that contains some of these objects.
My code looks like this.
Console.WriteLine("Give in the name you want to search for!");
string s = Console.ReadLine();
After this, I would like to check if the first property is "s", and if it is, display all of that given object's data on the screen.
Have a look at this and let me know if you're stuck with any of it :)
void Main()
{
List<Music> myMusic = new List<Music>
{
new Music
{
Artist = "Mozart",
Album = "Mozarts amazing album",
TotalTracks = int.MaxValue,
Etc = int.MinValue
},
new Music
{
Artist = "Foo",
Album = "Bar",
TotalTracks = int.MaxValue,
Etc = int.MinValue
},
};
var mozartsMusic = myMusic.Where(music => music.Artist == "Mozart")
.ToList();
mozartsMusic.ForEach(Console.WriteLine);
}
public class Music
{
public string Artist { get; set; }
public string Album { get; set; }
public int TotalTracks { get; set; }
public int Etc { get; set; }
public override string ToString()
{
return string.Join("\n",this.GetType().GetProperties().Select(p=>string.Format("{0} {1}", p.Name, p.GetValue(this))));
}
}
Something like this would do the trick:
class Datum
{
public string Composer { get; set; }
///wharever other proerties you need
public string DisplayOutput()
{
return this.Composer //+ however you want it displayed
}
}
class Program
{
static void Main(string[] args)
{
List<Datum> data = new List<Datum>();
foreach (var outputLine in data.Where(d => d.Composer == "Mozart").Select(d=>d.DisplayOutput())
{
Console.WriteLine(outputLine);
}
}
}
That should be a possible way to do so:
class Composer
{
public Composer( string lastName, string firstName, int year, int month )
{
LastName = lastName;
FirstName = firstName;
YearOfBirth = year;
MonthOfBirth = month;
}
public string LastName { get; set; }
public string FirstName { get; set; }
public int YearOfBirth { get; set; }
public int MonthOfBirth { get; set; }
public override string ToString()
{
return string.Format( "{0} {1} {2} {3}", LastName, FirstName, YearOfBirth.ToString(), MonthOfBirth.ToString() );
}
}
class Program
{
private static new List<Composer> composerList = new List<Composer>();
static void Main( string[] args )
{
composerList.Add( new Composer( "Mozart", "Wolfgang", 1756, 1 ) );
composerList.Add( new Composer( "Vivaldi", "Antonio", 1678, 3 ) );
Console.WriteLine( "Please enter a name you want to search for!" );
string name = Console.ReadLine();
ShowComposerData( name );
}
private static void ShowComposerData( string name )
{
foreach( Composer comp in composerList )
{
if( comp.LastName == name )
{
Console.WriteLine( comp.ToString() );
}
}
}
}

How to place values from struct to an array?

I'm trying to do it like bellow, but for next operations i would like to output an array that consist of 3-5 structs.
I would like to do it like : string[] my_array = {struct1,struct2,struct3}; but don't know how to do it correct.
public struct student
{
public string Name { get; set; }
public string Last_Name { get; set; }
public DateTime Birthday { get; set; }
public string Address { get; set; }
public string City { get; set; }
public int Zip { get; set; }
public string Country { get; set; }
}
class H
{
static void Main(string[] args)
{
student student_info = new student();
student_info.Name = "Mike";
student_info.Last_Name = "Johnson";
student_info.Birthday = new DateTime(1983, 12, 03);
student_info.Address = "Baker str. 84/4a";
student_info.City = "New LM";
student_info.Zip = 90541;
student_info.Country = "Paris";
string[] my_array = { student_info.Name, student_info.Last_Name, student_info.Birthday.ToString(), student_info.Address, student_info.City, student_info.Zip.ToString(), student_info.Country };
for (int counter = 0; counter < my_array.Length; counter++)
{
Console.WriteLine(my_array[counter]);
}
}
}
I'm not completely sure I understand what you're doing. But here's my best guess.
If the objects will all be of the same struct, you can just use that.
student[] args = new [] { struct1, struct2, struct3 };
If they aren't the same type, the greatest common denominator between three structs like this will be object. So,
object[] args = new object[] { struct1, struct2, struct3 };
If you'd like, on the other hand, to combine the three structs into a single string array as you've shown us, that's a little different, and I can show you if you confirm that that is actually what you were looking for.
You can create an array of the struct.
student[] my_array = new student[] {struct1,struct2,struct3};

C# Trouble adding to a generic list

This is a follow up question from another post but that post was answered. I have a for loop that I want to add three items to a generic class and I'm not sure how to do that. How do I add those items?
private static void TestResults()
{
List<Record> Records = new List<Record>();
for (int i = 0; i < ProxyList.Count; i++)
{
string[] split = List[i].Split('|');
// This is what i dont know how to do
// split[0] = Name, split[1] = SomeValue and split[3] = OrderNr
}
}
class Records
{
public static string Name { get; set; }
public static int SomeValue { get; set; }
public static int OrderNr { get; set; }
}
The first step is to associate the fields with instances of Records vs. the type itself. This is done by removing the static modifier
class Records
{
public string Name { get; set; }
public int SomeValue { get; set; }
public int OrderNr { get; set; }
}
To actually create instances try the following
for (int i = 0; i < ProxyList.Count; i++) {
string[] split = List[i].Split('|');
Records record = new Records() {
Name = split[0]
SomeValue = Int32.Parse(split[1])
OrderNr = Int32.Parse(split[2])
};
Records.add(record);
}
This particular example uses an object initializer to combine the acts of creating the object and settings its fields. This could be expanded into the longer form as follows
for (int i = 0; i < ProxyList.Count; i++) {
string[] split = List[i].Split('|');
Records record = new Records();
record.Name = split[0];
record.SomeValue = Int32.Parse(split[1]);
record.OrderNr = Int32.Parse(split[2]);
Records.add(record);
}
The Int32.Parse method will throw an exception if the item in the original string wasn't a number. If this is a possibility (think bad input) then you'll want to wrap the creation of Records with a try / catch statement
Well for one thing, your properties must not be static. You want different data for each instance, right? So they need to be instance properties. Personally I'd also make the type immutable, but that's another matter:
class Record // Changed from Records; each object is only a single record...
{
public string Name { get; set; }
public int SomeValue { get; set; }
public int OrderNumber { get; set; }
}
private static List<Record> ConvertRecords(IEnumerable<string> lines)
{
List<Record> records = new List<Record>();
foreach (string line in lines)
{
string[] split = line.Split('|');
Record record = new Record {
Name = split[0],
SomeValue = int.Parse(split[1]),
OrderNumber = int.Parse(split[2]);
};
records.Add(record);
}
}
As of C# 3 / .NET 3.5, a more idiomatic approach would be to use LINQ:
private static List<Record> ConvertRecords(IEnumerable<string> lines)
{
return (from line in lines
let split = line.Split('|')
select new Record {
Name = split[0],
SomeValue = int.Parse(split[1]),
OrderNumber = int.Parse(split[2]);
}).ToList();
}
}
... on the other hand, that's relatively advanced if you're really just starting to learn the language.
To be honest, Stack Overflow is better for asking specific questions than structured learning - I suggest you get hold of a good book, such as C# 4 in a Nutshell.
I'm not sure why you use static !!! but try this :
private static void TestResults()
{
List<Record> Records = new List<Record>();
for (int i = 0; i < ProxyList.Count; i++)
{;
string[] split = List[i].Split('|');
Records.Add(new Record() {Name = Namesplit[0] , SomeValue = split[1], OrderNr = split[3]}) ;
}
}

How to add comma seperated string values in dictionary type session variable

I am using c#
I have got below string in my variable.
string results = "Mr,Mike,Lewis,32,Project Manager,India";
Now I want to add these values in Dictionary type of session variable. I have declared a dict type variable in my code.
Dictionary<string, string> skywardsDetails = new Dictionary<string, string>();
Write now what I have written code was like below:
if (!string.IsNullOrEmpty(results))
{
string[] array = results.Split(',');
string title = array[0];
string firstname = array[1];
string lastname = array[2];
string age = array[3];
string designation = array[4];
string country = array[4];
//Here I want to write the new code which will add the results.Split(',') values in my Session variable as a Dictionary type.
foreach (string key in results.Split(','))
{
skywardsDetails.Add(key,//What to do here)
}
}
Please suggest
Your CSV results variable doesn't represent a dictionary. It represents an Employee model:
public class Employee
{
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Designation { get; set; }
public string Country { get; set; }
}
and then:
var tokens = (results ?? string.Empty).Split(',');
if (tokens.Length > 5)
{
var employee = new Employee
{
Title = tokens[0],
FirstName = tokens[1],
LastName = tokens[2],
Age = int.Parse(tokens[3]),
Designation = tokens[4],
Country = tokens[5]
};
// TODO: do something with this employee like adding it
// to some dictionary, session, whatever
}
You cant really use foreach here and instead of declaring local variables replace that part with
skywardsDetails["title"] = array[0];
skywardsDetails["firstname"] = array[1];
skywardsDetails["lastname"] = array[2];
skywardsDetails["age"] = array[3];
skywardsDetails["designation"] = array[4];
skywardsDetails["country"] = array[5];
Now move those string constants to some constant like const string Title="title" and you will be able to get required field data from your dictionary like
string title= skywardsDetails[Constants.Title]
It would make more sense to use the dictionary like this:
skywardsDetails.Add("Title", array[0]);
skywardsDetails.Add("FirstName", array[1]);
// etc.
You shouldn't use the actual values as keys, as i think you want a generic way to access them.
Try something like this:
enum UserData
{
Title,
Firstname,
Lastname,
Age,
Designation,
Country
}
//========================================================
string results = "Mr,Mike,Lewis,32,Project Manager,India";
string[] array = results.Split(',');
var skywardsDetails = new Dictionary<UserData, string>();
// maybe you need some check data here
for (int i = 0; i < array.Length; i++)
{
skywardsDetails[(UserData)i] = array[i];
}

Categories