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"};
Related
I'm looping through some logic for a program I'm making that reads text through a .txt file and every time I get to the place where the algorithm adds a Class Object I created it works but then the next time it hits it the previous object gets its data changed to the object currently being added and so on.
Here is a Snippet of code for preface this is inside While loop and nested in 3 if statements.
Question: Why is it overwriting all the other entries?
My logic is 100% working I ran tests on it for over 10 hours with many breakpoints also please go easy on me I'm semi proficient at C#
if (Att == a1)
{
Student s1 = new Student();
s1.Eid = Eid;
s1.Name = Name;
s1.Attempt1 = att1;
AllStudents.Add(s1);
//AllStudents.Add(new Student(Eid,Name, att1));
Eid = line;
Att = "";
qnum = 1;
counter = 1;
}
Here is my Student class
public class Student
{
public string Eid { get; set; }
public string Name { get; set; }
public string[] Attempt1 { get; set; }
public string[] Attempt2 { get; set; }
public string[] Attempt3 { get; set; }
public string[] Att1filler = { "n/a", "n/a", "n/a", "n/a", "n/a", "n/a" };
public string[] Att2filler = {"n/a","n/a","n/a","n/a","n/a","n/a"};
public string[] Att3filler = {"n/a","n/a","n/a","n/a","n/a","n/a"};
public int FinalGrade { get; set; }
public int Grade1 { get; set; }
public int Grade2 { get; set; }
public int Grade3 { get; set; }
public int Grade4 { get; set; }
public Student()
{
FinalGrade = 0;
Attempt1 = Att1filler;
Attempt2 = Att2filler;
Attempt3 = Att3filler;
}
public Student(string Eagid, string name, string[] Att1)
{
Eid = Eagid;
Name = name;
Attempt1 = Att1;
Attempt2 = Att2filler;
Attempt3 = Att3filler;
FinalGrade = 0;
}
public Student(string Eagid, string name, string[] Att1, string[] Att2)
{
Eid = Eagid;
Name = name;
Attempt1 = Att1;
Attempt2 = Att2;
Attempt3 = Att3filler;
FinalGrade = 0;
}
public Student(string Eagid, string name, string[] Att1, string[] Att2, string[] Att3)
{
Eid = Eagid;
Name = name;
Attempt1 = Att1;
Attempt2 = Att2;
Attempt3 = Att3;
FinalGrade = 0;
}
}
And finally this is how I declared my List
public List<Student> AllStudents = new List<Student>();
also the AllStudents.add(new Student(Eid,Name, att1)); is from another solution i found that still did not work for me.
I figured it out. Learned my lesson of passing by references vs passing by value. make sure if your algorithm is looping that anything that is initialized by new and is used inside the loop is re-initialized inside the loop so you don't just pass the same reference for each object.(sorry if this answer isn't 100% I'm running on 2 hours of sleep trying to get this project done!)
I have below scenario:
This is my class structure :
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public System.Collections.ObjectModel.Collection<Likes> Likes { get; set; }
}
public class Likes
{
public string Sport { get; set; }
public string Music { get; set; }
public string Food { get; set; }
public string Place { get; set; }
}
When I serialize object of User class then it will generate the below json string :
{"FirstName":"Naresh",
"LastName":"Parmar",
"Likes": [{"Sport":"Cricket",
"Music":"Classic",
"Food":"Gujarati",
"Place":"India"}]
}
I want to generate above json string like below:
{"FirstName":"Naresh",
"LastName":"Parmar",
"Sport":"Cricket",
"Music":"Classic",
"Food":"Gujarati",
"Place":"India"
}
I want the nested properties as primary one.
Any help would be appreciated.
Thanks in advance..
EDIT:
{"FirstName":"Naresh",
"LastName":"Parmar",
"Sport":"Cricket,Chess,Football",
"Music":"Classic",
"Food":"Gujarati",
"Place":"India"
}
It's really bad practice, since the code i'll post bellow doesn't have great maintainability, however if that's what you looking for, you can use this. Another class that have the format that you'd like, and have a method that adds a list of likes to the format you've required. That the class you should serialize to JSON:
class NestedUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Sport { get; set; }
public string Music { get; set; }
public string Food { get; set; }
public string Place { get; set; }
public void AddLikes(System.Collections.ObjectModel.Collection<Likes> likes)
{
foreach (Likes like in likes)
{
Sport += like.Sport + ",";
Music += like.Music + ",";
Food += like.Food + ",";
Place += like.Place + ",";
}
if (Sport != string.Empty)
{
Sport = Sport.Substring(0, Sport.Length - 1);
}
if (Music != string.Empty)
{
Music = Music.Substring(0, Music.Length - 1);
}
if (Food != string.Empty)
{
Food = Food.Substring(0, Food.Length - 1);
}
if (Place != string.Empty)
{
Place = Place.Substring(0, Place.Length - 1);
}
}
}
Since it's not only limited to Likes objects I'd suggest using dynamic objects. So the User class I propose is as follows:
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public dynamic Details { get; set; }
public User()
{
Details = new ExpandoObject();
}
public void AddSingleDetail(string key, string value)
{
var dict = this.Details as IDictionary<string, Object>;
if (dict.ContainsKey(key))
{
dict[key] += "," + value;
}
else
{
dict[key] = value;
}
}
public void AddDetails(object detailsObject)
{
var type = detailsObject.GetType();
foreach (var prop in type.GetProperties())
{
AddSingleDetail(prop.Name, prop.GetValue(detailsObject).ToString());
}
}
}
You can use it for adding single proerpties or adding an object as a whole. I used reflection to get all the property name and values and add them to the user details.
Sample usage:
static void Main(string[] args)
{
var user1 = new User() { FirstName = "Homer", LastName = "Simpson" };
user1.AddSingleDetail("Sport", "Bowling");
user1.AddSingleDetail("Sport", "Sleeping");
user1.AddSingleDetail("Food", "Donut");
user1.AddSingleDetail("Music", "Rock");
string flattenedHomer1 = ConvertUserToFlattenedJson(user1);
var user2 = new User() { FirstName = "Homer", LastName = "Simpson" };
var likes1 = new Likes() { Food = "Donut", Music = "Rock", Place = "Springfield", Sport = "Bowling" };
var likes2 = new Likes() { Food = "Steaks", Music = "Metal", Place = "Evergreen Terrace", Sport = "Sleeping" };
var proStuff = new ProfessionalStuff() { Title = "Boss" };
user2.AddDetails(likes1);
user2.AddDetails(likes2);
user2.AddDetails(proStuff);
string flattenedHomer2 = ConvertUserToFlattenedJson(user2);
}
And the method performing the JSON conversion is:
public static string ConvertUserToFlattenedJson(User u)
{
dynamic flatUser = new ExpandoObject();
flatUser.FirstName = u.FirstName;
flatUser.LastName = u.LastName;
var dict = u.Details as IDictionary<string, Object>;
foreach (var like in dict)
{
((IDictionary<string, Object>)flatUser)[like.Key] = like.Value;
}
string json = Newtonsoft.Json.JsonConvert.SerializeObject(flatUser);
return json;
}
In my sample above user2 is converted to the following JSON string which I believe is what you are looking for:
{
"FirstName": "Homer",
"LastName": "Simpson",
"Sport": "Bowling,Sleeping",
"Music": "Rock,Metal",
"Food": "Donut,Steaks",
"Place": "Springfield,Evergreen Terrace",
"Title": "Boss"
}
While concatenating strings you can check for null or duplicate values. I didn't handle that part.
For the sake of completeness, here's the ProfessionalStuff class I made up:
public class ProfessionalStuff
{
public string Title { get; set; }
}
Hope this helps.
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() );
}
}
}
}
So I'm completely new to programming; I've read the many similar questions and respective answers on here, and spent more time than I'd like to admit trying different ways of solving my problem, but I can't seem to find where the problem lies. Anyway, here's my code:
public struct City
{
public string cityName { get; set; }
public float cityTemp { get; set; }
}
class Program
{
static void Main(string[] args)
{
var cityList = new List<City>();
cityList.Add(new City
{
cityName = "Stockholm",
cityTemp = 22.65f
});
Console.WriteLine("List: ");
Console.WriteLine(cityList);
Console.ReadKey();
}
}
How do I make the list store my structs and how do I display the list properly?
Edit: I know I need to use foreach, this code was just a barebones representation of my problem.
You want something like this:
public struct City
{
public string cityName { get; set; }
public float cityTemp { get; set; }
}
class Program
{
static void Main(string[] args)
{
var cityList = new List<City>();
cityList.Add(new City
{
cityName = "Stockholm",
cityTemp = 22.65f
});
cityList.Add(new City
{
cityName = "London",
cityTemp = 25.24f
});
Console.WriteLine("List: ");
foreach (var city in cityList)
{
Console.WriteLine(string.Format("City: {0} is currently: {1}oC", city.cityName, city.cityTemp);
}
Console.ReadKey();
}
}
You could also make your city output a sensible response by overriding ToString() like this:
public struct City
{
public string cityName { get; set; }
public float cityTemp { get; set; }
public override string ToString()
{
return String.Format("City: {0} is currently: {1}oC", cityName, cityTemp);
}
}
So then you could have:
class Program
{
static void Main(string[] args)
{
var cityList = new List<City>();
cityList.Add(new City
{
cityName = "Stockholm",
cityTemp = 22.65f
});
cityList.Add(new City
{
cityName = "London",
cityTemp = 25.24f
});
Console.WriteLine("List: ");
foreach (var city in cityList)
{
Console.WriteLine(city);
}
Console.ReadKey();
}
}
The list is storing your structs. As for displaying them, that doesn't work by magic. You'll have to loop over the list and display each one.
public struct City
{
public string cityName { get; set; }
public float cityTemp { get; set; }
public override string ToString()
{
return String.Format("{0} {1}", cityName, cityTemp);
}
}
public void DisplayAll(IEnumerable<City> cities)
{
foreach (var city in cities)
Console.WriteLine(city);
}
You need to loop over your list of cities to display them:
Console.WriteLine("List: ");
foreach(var city in cityList)
{
Console.WriteLine(city.cityName + " " + city.cityTemp);
}
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.