I have the following C# class:
class BatchData
{
public string batchNumber { get; set; }
public string processDate { get; set; }
public int TotalRecords { get; set; }
public int SuccessCount { get; set; }
}
and a dictionary:
Dictionary<int, BatchData> BatchData = new Dictionary<int, BatchData>();
Now, I want to search the whole dictionary to see if the value
x
is held in:
BatchData.batchNumber
eg
for the whole dictionary, if
BatchData.batchNumber = x
I know Dictionary has a method
.contains
But I am not sure how I can apply this.
EDIT:
BatchData.batchNumber = x
Can occur multiple times within the dictionary
You could do this:
BatchData.Values.Any(x=>x.batchNumber == "x");
For example:
Dictionary<int, BatchData> BatchData = new Dictionary<int, BatchData>();
BatchData.Add(1, new BatchData { batchNumber = "x"});
var hasX = BatchData.Values.Any(x=>x.batchNumber == "x"); //true;
A dictionary is a collection of KeyValuePair objects, each of which has a Key property (an int in your case), and a Value property (a BatchData object).
There could be multiple entries with that batch number. If you just want to see if any key contains that number you can use
batchData.Any(kvp => kvp.Value.batchNumber == x);
If you want all key-value pairs with that batch number, change to Where:
batchData.Where(kvp => kvp.Value.batchNumber == x);
You can also use First, Single, etc. as appropriate.
You should use batchNumber as the key to your dictionary:
Dictionary<string, BatchData> BatchData = new Dictionary<string, BatchData>();
BatchValues.Add(batch1.batchNumber, batch1);
BatchValues.Add(batch2.batchNumber, batch2);
BatchValues.Add(batch3.batchNumber, batch3);
...
Then checking for existence is an O(1) operation (link):
BatchValues.ContainsKey(batchNumber);
You can use another one solution by Contains method from System.Linq.
First, you need to implement IEqualityComparer<> interface
public class BatchDataComparer : IEqualityComparer<KeyValuePair<int, BatchData>>
{
public bool Equals(KeyValuePair<int, BatchData> x, KeyValuePair<int, BatchData> y)
{
return (x.Value.batchNumber == y.Value.batchNumber);
}
public int GetHashCode(KeyValuePair<int, BatchData> obj)
{
//or something else what you need
return obj.Value.batchNumber.GetHashCode();
}
}
After that, you can get value from Dictionary like this:
private static void Main(string[] args)
{
Dictionary<int, BatchData> dic = new Dictionary<int, BatchData>();
dic.Add(1, new BatchData() { batchNumber = "x" });
dic.Add(2, new BatchData() { batchNumber = "y" });
dic.Add(3, new BatchData() { batchNumber = "z" });
bool contain = dic.Contains(new KeyValuePair<int, BatchData>(100, new BatchData()
{
batchNumber = "z"
}), new BatchDataComparer());
Console.ReadKey();
}
public class BatchData
{
public string batchNumber { get; set; }
public string processDate { get; set; }
public int TotalRecords { get; set; }
public int SuccessCount { get; set; }
}
Related
Let me explain, I have a model list in which I have a little more than a thousand parameters, so I have to fill the list with some variables, the thing is that I don't want to do this:
list.Add(new Model{
name1= value,
name2= value,
.....
name1000=value
});
I have an array that contains the names of the parameters in the list, so I was wondering if is possible to use that array of the names and in a loop get the variables fill in, something like this:
list.Add(new Model{
//a loop?
array[0]= value
});
Thanks.
You can achieve this using reflection. Code below
public class ModelFactory
{
private IDictionary<string, PropertyInfo> propertiesInfo { get; set; }
public ModelFactory()
{
this.propertiesInfo = typeof(Model)
.GetProperties()
.ToDictionary(p => p.Name, p => p);
}
public Model Create(string[] propertiesToInitialize, dynamic value)
{
var model = new Model();
foreach (var propertyName in propertiesToInitialize)
{
if (this.propertiesInfo.ContainsKey(propertyName))
{
var property = this.propertiesInfo[propertyName];
property.SetValue(model, value);
}
}
return model;
}
}
Model to initialize
public class Model
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
public int MyProperty3 { get; set; }
public int MyProperty4 { get; set; }
public int MyProperty5 { get; set; }
}
Usage
public void Test()
{
var propertiesToInitialize = new string[] { "MyProperty1", "MyProperty2", "MyProperty4" };
var modelFactory = new ModelFactory();
var list = new List<Model>();
list.Add(modelFactory.Create(propertiesToInitialize, 500));
Console.WriteLine("MyProperty1 " + list[0].MyProperty1); // 500
Console.WriteLine("MyProperty2 " + list[0].MyProperty2); // 500
Console.WriteLine("MyProperty3 " + list[0].MyProperty3); // 0
Console.WriteLine("MyProperty4 " + list[0].MyProperty4); // 500
Console.WriteLine("MyProperty5 " + list[0].MyProperty5); // 0
}
However as already mentioned in comments, please reconsider your model design because model with these many properties is not optimal.
I have a class:
public class Foo
{
public string Name { get; set; }
public double Value { get; set; }
public override string ToString()
{
return Name;
}
}
And I need to create a dictionary where key is object of Foo. Like this:
Foo foo1 = new Foo { Name = "Foo1", Value = 2.2 };
Foo foo2 = new Foo { Name = "Foo2", Value = 3.6 };
Dictionary<Foo, int> dic = new Dictionary<Foo, int>();
dic.Add(foo1, 1234);
dic.Add(foo2, 2345);
And now I want to get values from dictionary by passing Foo.Name property as key. Like this:
int i=dic["Foo1"];
// i==1234
i = dic["Foo2"];
// i==2345
Is it possible? Or the only way to pass object of Foo as key and override Equals method?
If you use a Foo as a key, you will need to use a Foo to index the dictionary as well.
Provided that what you actually need is most likely a Dictionary<string, int>, you could try overriding GetHashCode and Equals so that you can compare Foo objects based on the name only:
using System.Collections.Generic;
public class Foo {
public string Name { get; set; }
public double Value { get; set; }
public override string ToString() {
return Name;
}
public override int GetHashCode() {
return Name.GetHashCode();
}
public override bool Equals(object obj) {
Foo other = obj as Foo;
if (other == null) {
return false;
}
return Name.Equals(other.Name);
}
}
class Program {
static void Main(string[] args) {
Foo foo1 = new Foo { Name = "Foo1", Value = 2.2 };
Foo foo2 = new Foo { Name = "Foo2", Value = 3.6 };
Dictionary<Foo, int> dic = new Dictionary<Foo, int>();
dic.Add(foo1, 1234);
dic.Add(foo2, 2345);
int i = dic[new Foo { Name = "Foo1" }];
}
}
How about this:
class Program
{
public class Foo
{
public string Name { get; set; }
public double Value { get; set; }
public override string ToString()
{
return Name;
}
}
static void Main(string[] args)
{
Foo foo1 = new Foo { Name = "Foo1", Value = 2.2 };
Foo foo2 = new Foo { Name = "Foo2", Value = 3.6 };
var dic = new Dictionary<string, KeyValuePair<Foo, int>>();
dic.Add(foo1.Name, new KeyValuePair<Foo, int>(foo1, 1234));
dic.Add(foo2.Name, new KeyValuePair<Foo, int>(foo2, 2345));
int x = dic["Foo1"].Value;
var y = dic["Foo2"].Value;
Console.WriteLine(x);
Console.WriteLine(y);
Console.ReadKey();
}
}
Result will be:
1234
2345
The Dictionary is based on a hash table, that means it uses a hash lookup, which is a rather efficient algorithm to look up things. I suggest you think on your design and just use Dictionary<string,int>if you just want to use string as key
As a work around( not preferred way use only if you can't change your design), you could do this.
var key = dic.Keys.FirstOrDefault(c=>c.Name == "Foo1");
if(key != null)
dic[key]; //
Ok. I solved it by creating a class inherits Dictionary and overriding get value method. This solves my problem but I'm not sure about productivity with large collections.
public class MyDictionary:Dictionary<Foo, int>
{
public Bar():base()
{
}
new public int this[string key]
{
get
{
return this[base.Keys.Single(a => a.Name == key)];
}
}
}
And then this code works well:
MyDictionary<Foo, int> dic = new MyDictionary<Foo, int>();
dic.Add(foo1, 1234);
dic.Add(foo2, 2345);
int i=dic["Foo1"];
This question already has answers here:
C# Dictionary with two Values per Key?
(10 answers)
Closed 6 years ago.
What's the easiest way to create a collection of key, value1, value2 ?
Important to me is that it is easy & short to retrieve either value1 or value2 given the pair (please show an example)
I know I can do this -
class MyObject
{
internal string NameA { get; set; }
internal string NameB { get; set; }
}
class Other
{
Dictionary<string, MyObject> MyObjectCollection { get; set; }
private void function()
{
MyObjectCollection = new Dictionary<string, MyObject>()
{ { "key", new MyObject { NameA = "something", NameB = "something else" } } };
var valueA = MyObjectCollection["key"].NameA; // = "something"
}
}
Is there a better way?
The solution which is easiest to implement (Dictionary<String, Tuple<String, String>>) is not the one which is easiest to support and develop (what is MyObjectCollection[key].Value2?). So I suggest using your own class:
class MyPair {
public string NameA { get; internal set; }
public string NameB { get; internal set; }
public MyPair(nameA, nameB) {
NameA = nameA;
NameB = nameB;
}
public override String ToString() {
return $"NameA = {NameA}; NameB = {NameB}";
}
}
class Other {
// you don't want "set" here
// = new ... <- C# 6.0 feature
public Dictionary<string, MyPair> Data { get; } = new Dictionary<string, MyPair>() {
{"key", new MyPair("something", "something else")},
};
...
Other myOther = new Other();
String test = myOther.Data["key"].NameA;
You can use a Tuple:
Dictionary<string,Tuple<string,string>> MyObjectCollection {get; set;}
private void function()
{
MyObjectCollection = new Dictionary<string, Tuple<string,string>>();
MyObjectCollection.Add("key1", Tuple.Create("test1", "test2"));
}
List<MyObject> list = new List<MyObject>();
var res = list.ToDictionary(x => x, x => string.Format("Val: {0}", x));
The first lambda lets you pick the key, the second one picks the value.
It's quite hard for me to explain this, but I will give it a go.
Objective:
Create a LINQ query that will return a dictionary of data. However it must be a dictionary of the model which I am using.
View Model:
public class ValueBySupplierAndClaimTypeViewModel : ReportViewModel
{
public IQueryable<ValueBySupplierAndClaimTypeModel> ReportData {get; set; }
public TotalValueBySupplierAndClaimTypeModel ReportTotalData { get; set; }
public Dictionary<string, decimal> DictionaryData { get; set; }
public string output { get; set; }
}
Interface:
Dictionary<string, decimal> DictData;
TotalValueBySupplierAndClaimTypeModel GetTotalValueBySupplierAndClaimType(
int ClientID, int ReviewPeriodID, int StatusCategoryID);
SQL Repository:
public TotalValueBySupplierAndClaimTypeModel GetTotalValueBySupplierAndClaimType(int ClientID, int ReviewPeriodID, int StatusCategoryID)
{
var rt =
this.GetValueBySupplierAndClaimType(ClientID, ReviewPeriodID, StatusCategoryID);
TotalValueBySupplierAndClaimTypeModel x = new TotalValueBySupplierAndClaimTypeModel()
{
NormalTotal = rt.Sum(c=>c.Normal) ?? 0,
QueryTotal = rt.Sum( c => c.Query) ?? 0,
StrongTotal = rt.Sum( c => c.Strong) ?? 0
};
return x;
}
I'm really not sure how to do this. Can anybody help?
I have this function that converts an object to a dictionary. It gets all the properties of the class, as the dictionary's keys. May be you can modify it to meet your needs:
public Dictionary<string, object> ConvertClassToDict(object classToConvert)
{
Dictionary<string, object> result = new Dictionary<string, object>();
PropertyInfo[] properties = classToConvert.GetType().GetProperties();
List<string> propertiesNames = properties.Select(p => p.Name).ToList();
foreach (var propName in propertiesNames)
{
PropertyInfo property = properties.First(srcProp => srcProp.Name == propName);
var value = property.GetValue(classToConvert, null);
result.Add(propName, value);
}
return result;
}
The argument classToConvert, is just an instance of any class.
Similar to #lukiller's answer, but with LINQ:
public Dictionary<string, object> MapToDictionary(object instance)
{
if(instance == null) return null;
return instance.GetType()
.GetProperties()
.ToDictionary(p => p.Name,
p => p.GetValue(instance));
}
For example, let's suppose we have the following class:
public class User
{
public string Username { get; set; }
public string Password { get; set; }
}
We can print it like this (one line):
MapToDictionary(new User()
{
Username = "mcicero",
Password = "abc123"
}).ToList().ForEach(i => Console.WriteLine("{0}: {1}", i.Key, i.Value));
This prints out:
Username: mcicero
Password: abc123
I am trying to compare all possible values in a list of objects like this:
public class Object21
{
int Id,
bool firstbool,
bool secondbool
}
I would loop through the objects and compare them like this:
List<Object1> objects;
foreach(var o in objects)
{
if(firstbool && secondbool)
....
if(firstbool && !secondbool)
....
if(!firstbool && secondbool)
....
if(!firstbool && !secondbool)
....
}
This seems ok, but what if the object had several values that you were running through if statements.
public class Object2
{
int Id;
int firstbool;
....
int twentiethbool;
}
Then you would have to write out all of the possible conditional statements and your code would be terribly written and hard to read.
List<Object2> objects2;
foreach(var o in objects2)
{
if(firstbool && secondbool && ... && twentiethbool)
....
if(....)
....
....
....
if(!firstbool && !secondbool && ... && !twentiethbool)
....
}
Is there a simpler way to write the second scenario so that you are not writing every combination of if statements?
In the end I would like to calculate the percentage occurrence of each condition in the list.
To answer the first part of the question (about comparing every combination):
There isn't really a good way to do that, other than write a bunch of if statements. Of course; you probably shouldn't be doing that anyways :)
You could probably use reflection and recursion, but thats going to get messy really fast.
Luckily, to just get the percentage occurrence of each flag, you can just do:
list.Count(i => i.firstbool) / (double)list.Count();
...
first, create a dictionary to save all conditions
var dict = new Dictionary<string, int>{{"001",0},{"010",0} ...}
then, create key use bool values
var key=string.Empty;
key+=firstbool ?"0":"1"
key+=secondbool ?"0":"1"
......
after all, you can know which condition occurred
dict[key]++;
Given a class structure like this:
public class YourClass
{
public int Id { get; set; }
public bool firstbool { get; set; }
public bool secondbool { get; set; }
public bool thirdbool { get; set; }
}
You can use reflection to get all the boolean values (and only bool values) inside the class:
public IEnumerable<bool> GetBools(YourClass obj)
{
return obj.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(x => x.PropertyType == typeof (bool))
.Select(x => (bool)x.GetValue(obj, null));
}
Then use LINQ to iterate through the collection, and create a dictionary of combinations and totals:
List<YourClass> objects = new List<YourClass>();
var totals = objects.GroupBy(x => String.Join(",", GetBools(x)))
.ToDictionary(x => x.Key, x => x.Count() / (double)objects.Count);
This will give you a dictionary with each unique combination and the percentage it occurs.
Given this input:
var o = new List<YourClass>
{
new YourClass {firstbool = true, secondbool = true, thirdbool = false},
new YourClass {firstbool = false, secondbool = false, thirdbool = false},
new YourClass {firstbool = true, secondbool = true, thirdbool = false}
};
The result in the dictionary will be:
{["True,True,False", 0.666666666666667]}
{["False,False,False", 0.333333333333333]}
it's probably easier to rewrite your class, storing each condition in an array like follows:
public class MyObject
{
public static int numFields = 20;
public enum Conditions
{
C1, C2, C3, .... C20 //name for each condition, so can set values using descriptive names
};
public Boolean[] BinaryFields = new Boolean[numFields];
public void setCondition(Conditions condition, Boolean value)
{
BinaryFields[(int)condition] = value;
}
public override string ToString()
{
return string.Join(",", BinaryFields);
}
}
then you can calculate the stat by counting what is actually there, instead of numerating through all of the 2^20 possibilities. something like follows:
static void Main(string[] args)
{
//simulation: creat 10 MyObjects
List<MyObject> lst = new List<MyObject>();
for (int i = 0; i < 10; i++)
{
MyObject m = new MyObject();
//example of setting condition
m.setCondition(MyObject.Conditions.C1, true);
lst.Add(m);
}
//calculate stat
var resultCount = new Dictionary<string, int>(); //conditionResult, count
foreach (MyObject m in lst)
{
if (resultCount.ContainsKey(m.ToString()))
{
resultCount[m.ToString()] += 1;
}
else
{
resultCount.Add(m.ToString(), 1);
}
}
//print stat
foreach(KeyValuePair<string, int> entry in resultCount){
Debug.WriteLine("probability for conditoin={0} is {1}", entry.Key, (double)entry.Value / lst.Count);
}
}
If you have some unique action for each boolean properties combination I suggest you to use some kind of string key for your object, generated on those values. Something like "001001", "000000" etc. Then use Dictionary<string, Func<int>> to hold all your unique actions, get and perform the right one by it's key. For example:
public class Object21
{
public int Id { get; set; }
public bool FirstBool { get; set; }
public bool SecondBool { get; set; }
public bool ThirdBool { get; set; }
public bool FourthBool { get; set; }
public bool FifthBool { get; set; }
public bool SixthBool { get; set; }
public void Process()
{
// Perform the action
Actions[Key]();
}
// Returns "001001" like representation of your object
public string Key
{
get
{
return string.Join(string.Empty, GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(x => x.PropertyType == typeof(bool))
.Select(x => (bool)x.GetValue(this, null) ? "1" : "0" ));
}
}
private static Dictionary<string, Func<int>> Actions
{
get
{
return new Dictionary<string, Func<int>>
{
{"000000", new Func<int>(delegate
{
Console.WriteLine("000000 action performed.");
return 0;
})},
{"000001", new Func<int>(delegate
{
Console.WriteLine("000001 action performed.");
return 1;
})},
{"000010", new Func<int>(delegate
{
Console.WriteLine("000010 action performed.");
return 2;
})},
// More actions
{"111111", new Func<int>(delegate
{
Console.WriteLine("111111 action performed.");
return 63;
})}
};
}
}
}
And then use this in your program like this:
static void Main(string[] args)
{
var list = new List<Object21>
{
// initialize your list
};
foreach (var object21 in list)
{
object21.Process();
}
// Calculate your occurrences (basically what #Grant Winney suggested)
var occurrences = list.GroupBy(o => o.Key).ToDictionary(g => g.Key, g => (g.Count() / (double)list.Count)*100);
foreach (var occurrence in occurrences)
{
Console.WriteLine("{0}: {1}%", occurrence.Key, occurrence.Value);
}
}