I have a class with 5 members.
like that:
class Demo
{
public int id;
public string name;
public string color;
public int 4th_member;
public int 5th_member;
}
I have list of this class.
for the 4th_member, and 5th_member, I have 2 list of dictionary with int key and int value. (one for 4th, and the second for 5th)
I want to update these members, according to the dictionary.
like, if dictionary's key = id, then update 4th_member to be value of Dictionary.
I hope my question is clear enough.
I tested the below code its working fine.
Hope this will solve your problem if I have understood your question properly
var demo = demoTest.Select(s =>
{
s.Fourthth_member = dic.GetValueFromDictonary(s.Fourthth_member);
s.Fifthth_member = dic1.GetValueFromDictonary(s.Fifthth_member);
return s;
}).ToList();
//Extension method
public static class extMethod
{
public static int GetValueFromDictonary(this Dictionary<int, int> dic, int key)
{
int value = 0;
dic.TryGetValue(key, out value);
return value;
}
}
linq is not used for updating data but for queries. This is a possible solution:
foreach(var demo in demoList)
{
if(dictionaries[0].ContainsKey(demo.id))
{
demo.member4 = dictionaries[0][demo.id];
}
if (dictionaries[1].ContainsKey(demo.id))
{
demo.member5 = dictionaries[1][demo.id];
}
}
Or with the TryGetValue
foreach(var demo in demoList)
{
int value;
if(dictionaries[0].TryGetValue(demo.id, out value))
{
demo.member4 = value;
}
if (dictionaries[1].TryGetValue(demo.id, out value))
{
demo.member5 = value;
}
}
Related
I have a dictionary which stores members of a 'Skiing' tournament. It also stores there scores. What I want to do is be able to find and display the top 3 scores of the members. I was just wondering what the best way would be to approach this as I am stuck at the moment. The following is the dictionary and how a member is added:
public static Dictionary<string, Skier> Skiers = new Dictionary<string, Skier>();
static int income;
string lodgeName;
public SkiLodge(string newLodgeName)
{
newLodgeName = lodgeName;
Skiers = new Dictionary<string, Skier>();
}
static int newNumber = 1;
//ADD SKIER
public Skier AddSkier(string inName, string inAddress, int inScore)
{
string newNumberString = newNumber.ToString();
Skier result = new Skier(newNumberString, inName, inAddress, inScore);
newNumber = newNumber + 1;
Skier S = new Skier(newNumberString, inName, inAddress, inScore);
Skiers.Add(newNumberString, S);
income = income + 100;
return result;
}
I assumed that you have a property in Skier called Score, here how can you achieve your goal.
//Your dictionary must have at least 3 entries.
var orderedTopThree = Skiers.OrderByDescending(s => s.Value.Score).Take(3);
Either of these methods added to your SkiLodge class, will get you what you're looking for.
This will grab your top X KeyValuePairs with the Skier object being the Value property of the KeyValuePair.
public List<KeyValuePair<string,Skier>> GetTopSkiers(int howMany)
{
return Skiers.OrderByDescending(kvp => kvp.Value.Score).Take(howMany).ToList();
}
This will grab your top X Skiers
public List<Skier> GetTopSkiers(int howMany)
{
return Skiers.OrderByDescending(kvp => kvp.Value.Score).Take(howMany).Select(kvp => kvp.Value).ToList();
}
Both methods use the OrderByDescending Linq method, which uses a lambda expression as a selector for the sorting comparison kvp => kvp.Value.Score. Which in this case is saying, foreach kvp (KeyValuePair) in this dictionary, sort them by the Value property, which in this case is the Skier object, and use the Skier object's Score as the value to sort by.
Take will take, up to x values from an Enumerable.
Select then returns an Enumerable resulting from the lambda function passed in. In this case, kvp => kvp.Value returns an Enumerable of Skier objects, instead of a list of the KeyValuePair objects.
Either use a SortedDictionary or enumerate through the keys of dictionary or this code
public class Skier
{
public static Dictionary<string, Skier> Skiers = new Dictionary<string, Skier>();
public int inScore { get; set; }
public Skier()
{
int[] highscore = Skiers.AsEnumerable().OrderByDescending(x => ((Skier)x.Value).inScore).Take(3).Select(y => ((Skier)y).inScore).ToArray();
}
}
You may use LINQ to achieve. Here is one sample query:
Skiers.OrderByDescending(e=>e.Value.inScore).Take(3).ToList();
Using System.Linq, the following code will get you the best 3 Skiers by score:
public List<Skier> GetTop3()
{
var list = Skiers.OrderByDescending(sk=> sk.Value.Score).Take(3).ToList();
return list;
}
I have tried to replicate the behavior and fixed some of the issues in above code. In AddSkier you dont need to create 2 objects.
FetchTopThree() will give you the top 3 results. You can then display the results.
using System.Collections.Generic;
using System.Linq;
public class SkiLodge
{
public static Dictionary<string, Skier> Skiers = new Dictionary<string, Skier>();
static int income;
string lodgeName;
public SkiLodge(string newLodgeName)
{
this.lodgeName = newLodgeName;
}
static int newNumber = 1;
//ADD SKIER
public Skier AddSkier(string inName, string inAddress, int inScore)
{
string newNumberString = newNumber.ToString();
newNumber = newNumber + 1;
Skier skier= new Skier(newNumberString, inName, inAddress, inScore);
Skiers.Add(newNumberString, skier);
income = income + 100;
return skier;
}
public List<Skier> FetchTopThree()
{
return Skiers.Values.OrderByDescending(s => s.InScore).Take(3).ToList();
}
}
public class Skier
{
public string NewNumberString { get; }
public string InName { get; }
private readonly string inAddress;
public int InScore { get; }
public Skier(string newNumberString, string inName, string inAddress, int inScore)
{
this.NewNumberString = newNumberString;
this.InName = inName;
this.inAddress = inAddress;
this.InScore = inScore;
}
}
I was looking for a similar way to create an alias for something else like its possible in C using preprocessor (this question is a bit similar, couldn't find anything useful there).
This is the problem: I've got a method that receives an array, but each position of the array has a specific meaning, like they where different parameters with specific names. What I want to do is to make my code easier to read (and write) by using those specific names, but, on the other hand, I don't want to create another method call (like in example 1) nor assign the array positions to new variables (example 2), because the performance is critical.
Example 1:
void OriginalMethodSignature(Type[] values)
{
SimplifiedMethod(values[0], values[1], ... values[n]);
}
void SimplifiedMethod(Type specificName1, Type specificName2, ... Type specificNameN)
{
// simple implementation using specific names instead of values[n]
}
Example 2:
void OriginalMethodSignature(Type[] values)
{
Type specificName1 = values[0];
Type specificName2 = values[1];
...
Type specificNameN = values[n];
// simple implementation using specific names instead of values[n]
}
I cannot change the method signature because its used in a dellegate, the Type is fixed.
The next example is a bit better, but still not optimum:
void OriginalMethodSignature(Type[] values)
{
// implementation using values[specificName1] ... values [specificNameN]
}
const int specificName1 = 0;
const int specificName2 = 1;
...
const int specificNameN = n-1;
Is there any way to create an snippet for this purpose? If yes, how would it be?
There isn't any built in way to do what you wan't, because you shouldn't really be doing it at all. You should be using an object with properties instead of an array.
Anyway, you can make an object that encapsulates the array, so that the properties use the array as storage:
public class NamedObject {
private Type[] _values;
public NamedObject(Type[] values) {
_values = values;
}
public SpecificName1 { get { return _values[0]; } set { _values[0] = value; } }
public SpecificName2 { get { return _values[1]; } set { _values[1] = value; } }
public SpecificName3 { get { return _values[2]; } set { _values[2] = value; } }
public SpecificName4 { get { return _values[3]; } set { _values[3] = value; } }
public SpecificName5 { get { return _values[4]; } set { _values[4] = value; } }
public SpecificName6 { get { return _values[5]; } set { _values[5] = value; } }
}
Now you can use the object to access the array:
void OriginalMethodSignature(Type[] values) {
NamedObject obj = new NamedObject(values);
// get a value
Type x = obj.SpecificName4;
// set a value
obj.SpecificName2 = x;
}
Create a dedicated class or struct, and parse the array into it.
public class MyClassOfStuff
{
Type SpecificName1 {get;set;}
Type SpecificName2 {get;set;}
public static MyClassOfStuff Parse(Type[] value)
{
Type specificName1 = values[0];
Type specificName2 = values[1];
...
Type specificNameN = values[n];
}
}
void OriginalMethodSignature(Type[] values)
{
var mystuff = MyClassOfStuff.Parse(values);
}
I have a problem which I don't know how to solve. I have a class. This class has two arrays. I would like to get access via properties. How can I do it? I tried to use indexers, but it is possible if I have only one array. Here what I want to do:
public class pointCollection
{
string[] myX;
double[] myY;
int maxArray;
int i;
public pointCollection(int maxArray)
{
this.maxArray = maxArray;
this.myX = new string[maxArray];
this.myY = new double[maxArray];
}
public string X //It is just simple variable
{
set { this.myX[i] = value; }
get { return this.myX[i]; }
}
public double Y //it's too
{
set { this.myY[i] = value; }
get { return this.myY[i]; }
}
}
With this code, my X and Y are only simple variables, but not arrays.
If I use indexers, I get access only to one array:
public string this[int i]
{
set { this.myX[i] = value; }
get { return this.myX[i]; }
}
But how can I get access to second array?
Or I can't use property in this case? And I need only use:
public string[] myX;
public double[] myY;
An example with Tuples.
public class pointCollection
{
Tuple<String,Double>[] myPoints;
int maxArray;
int i;
public pointCollection(int maxArray)
{
this.maxArray = maxArray;
this.myPoints = new Tuple<String,Double>[maxArray];
}
public Tuple<String,Double> this[int i]
{
set { this.myPoints[i] = value; }
get { return this.myPoints[i]; }
}
}
And to access the points you do...
pointCollection pc = new pointCollection(10);
// add some data
String x = pc[4].Item1; // the first entry in a tuple is accessed via the Item1 property
Double y = pc[4].Item2; // the second entry in a tuple is accessed via the Item2 property
If I got it right, you need some kind or read/write-only wrapper for arrays to be exposed as properties.
public class ReadWriteOnlyArray<T>{
private T[] _array;
public ReadWriteOnlyArray(T[] array){
this._array = array;
}
public T this[int i]{
get { return _array[i]; }
set { _array[i] = value; }
}
}
public class pointCollection
{
string[] myX;
double[] myY;
int maxArray;
public ReadWriteOnlyArray<string> X {get; private set;}
public ReadWriteOnlyArray<double> Y {get; private set;}
public pointCollection(int maxArray)
{
this.maxArray = maxArray;
this.myX = new string[maxArray];
this.myY = new double[maxArray];
X = new ReadWriteOnlyArray<string>(myX);
Y = new ReadWriteOnlyArray<double>(myY);
}
}
and usage
var c = new pointCollection(100);
c.X[10] = "hello world";
c.Y[20] = c.Y[30] + c.Y[40];
The closest you'll come without either changing your data structure or moving to methods is to make a property that returns each array, much like you did in your first code block, except without the [i].
Then, you do var x = instanceOfPointCollection.MyX[someI]; for example.
I want to retrieve data from a list I created that contains class objects via a foreach but I'm not able to.
Can somebody please tell me what's missing in my code?
I have a class Recipes.cs that contains the following code:
public class Recipe
{
string _oveskrift;
int _recipe_id;
string _opskrift;
int _kcal;
public Recipe(string overskrift, int recipe_id, string opskrift,int kcal)
{
_oveskrift = overskrift;
_recipe_id = recipe_id;
_opskrift = opskrift;
_kcal = kcal;
}
}
public class Recipes
{
public List<Recipe> CreateRecipeList()
{
Recipe opskrift1 = new Recipe("Cornflakes med Chili",1,"4 kg cornflakes bages", 420);
Recipe opskrift2 = new Recipe("Oksemørbrad",2,"Oksemørbrad steges i baconfedt", 680);
Recipe opskrift3 = new Recipe("Tun i vand",3,"Dåsen åbnes og tunen spises", 120);
List<Recipe> Recipelist = new List<Recipe>();
Recipelist.Add(opskrift1);
Recipelist.Add(opskrift2);
Recipelist.Add(opskrift3);
return Recipelist;
}
}
I call CreateRecipeList() from another class calculator.cs and the code looks like this:
private int FindRecipes()
{
List<Recipe> Rlist = new List<Recipe>();
// CREATE THE CLASS AND ADD DATA TO THE LIST
Recipes r = new Recipes();
Rlist = r.CreateRecipeList();
int test = 0; // used only for test purposes
foreach(var rec in Rlist)
{
rec.????
test++;
}
return test;
}
I would presume that I should be able to dot my way into rec."the class object name"."the value"
But nothing happens!.
All I get is the option to rec.Equals, rec.GetHashcod ect. which is clearly wrong.
For the record I have also tried:
foreach(Recipe rec in Rlist)
{
rec.????
test++;
}
But that doesn't work either.
The Int test are only there for test purposes.. and it return 3.. so the list does contain the correct information.
Please show us the code for the Recipe class. Besides that, you're most of the way there...
foreach(Recipe rec in Rlist)
{
string str = rec.<PropertyName>;
}
You need to set the proper access modifiers for the members in your Recipe class.
public : Access is not restricted.
protected : Access is limited to the containing class or types derived from the containing class.
Internal : Access is limited to the current assembly.
protected internal: Access is limited to the current assembly or types derived from the containing class.
private : Access is limited to the containing type.
By default, the members of your Recipe class will have the private access modifier.
string _oveskrift;
int _recipe_id;
string _opskrift;
int _kcal;
is:
private string _oveskrift;
private int _recipe_id;
private string _opskrift;
private int _kcal;
Maybe you want to modify your member access as follows, in order to set the values of the members only inside the class code. Any attempt to set their values outside the Recipe class will fail, as the set is private. The get remains public, which makes the value available for reading.
public class Recipe
{
string _oveskrift;
int _recipe_id;
string _opskrift;
int _kcal;
public string Oveskrift
{
get
{
return _oveskrift;
}
private set
{
_oveskrift=value;
}
}
public int RecipeId
{
get
{
return _recipe_id;
}
private set
{
_recipe_id = value;
}
}
public string Opskrift
{
get
{
return _opskrift;
}
private set
{
_opskrift = value;
}
}
public int Kcal
{
get
{
return _kcal;
}
private set
{
_kcal = value;
}
}
public Recipe(string overskrift, int recipe_id, string opskrift, int kcal)
{
_oveskrift = overskrift;
_recipe_id = recipe_id;
_opskrift = opskrift;
_kcal = kcal;
}
}
Also, please read as soon as possible the following MSDN article: Capitalization Conventions. And also, this one: C# Coding Conventions (C# Programming Guide).
I'm trying to compare two complex objects in C#, and produce a Dictionary containing the differences between the two.
If I have a class like so:
public class Product
{
public int Id {get; set;}
public bool IsWhatever {get; set;}
public string Something {get; set;}
public int SomeOtherId {get; set;}
}
And one instance, thus:
var p = new Product
{
Id = 1,
IsWhatever = false,
Something = "Pony",
SomeOtherId = 5
};
and another:
var newP = new Product
{
Id = 1,
IsWhatever = true
};
To get the differences between these, i'm doing stuff that includes this:
var oldProps = p.GetType().GetProperties();
var newProps = newP.GetType().GetProperties();
// snip
foreach(var newInfo in newProps)
{
var oldVal = oldInfo.GetValue(oldVersion, null);
var newVal = newInfo.GetValue(newVersion,null);
}
// snip - some ifs & thens & other stuff
and it's this line that's of interest
var newVal = newInfo.GetValue(newVersion,null);
Using the example objects above, this line would give me a default value of 0 for SomeOtherId (same story for bools & DateTimes & whathaveyou).
What i'm looking for is a way to have newProps include only the properties that are explicitly specified in the object, so in the above example, Id and IsWhatever. I've played about with BindingFlags to no avail.
Is this possible? Is there a cleaner/better way to do it, or a tool that's out there to save me the trouble?
Thanks.
There is no flag to tell if you a property was explicitly set. What you could do is declare your properties as nullable types and compare value to null.
If i understand you correctly, this is what microsoft did with the xml wrapping classes, generated with the xsd utility, where you had a XIsSpecified, or something like that, for each property X.
So this is what You can do as well - instead of public int ID{get;set;}, add a private member _id , or whatever you choose to call it, and a boolean property IDSpecified which will be set to true whenever Id's setter is called
I ended up fixing the issue without using reflection (or, not using it in this way at least).
It goes, more or less, like this:
public class Comparable
{
private IDictionary<string, object> _cache;
public Comparable()
{
_cache = new Dictionary<string, object>();
}
public IDictionary<string, object> Cache { get { return _cache; } }
protected void Add(string name, object val)
{
_cache.Add(name, val);
}
}
And the product implementation goes to this:
public class Product : Comparable
{
private int _id;
private bool _isWhatever;
private string _something;
private int _someOtherId;
public int Id {get { return _id; } set{ _id = value; Add("Id", value); } }
public bool IsWhatever { get { return _isWhatever; } set{ _isWhatever = value; Add("IsWhatever ", value); } }
public string Something {get { return _something; } set{ _something = value; Add("Something ", value); } }
public int SomeOtherId {get { return _someOtherId; } set{ _someOtherId = value; Add("SomeOtherId", value); } }
}
And the comparison is then pretty straightforward
var dic = new Dictionary<string, object>();
foreach(var obj in version1.Cache)
{
foreach(var newObj in version2.Cache)
{
//snip -- do stuff to check equality
dic.Add(....);
}
}
Doesn't hugely dirty the model, and works nicely.