I am just curious whether or not this can be achieved: I have currently got a sort of problem where I am using controllers to set and get data inside a Class and this is done through methods and instances on the handler side.
I am just wondering, because doing public string x { get; set; } can become very long winded for each property that your project consists of.
Is there a way that I can achieve this sort of ideology inside a Class?
public core Array[] (
Option1 => string Array[] (
Name => 'example'
),
Option2 => String Array[] (
Name => 'example2'
) { set; get; }
);
Of course, this is just a theory and won't be the exact solution. I am wondering if I'd:
1) Need a controller when appending data to the index's.
2) Need to instance the Class that the Controller handles or if I can do it through Main Class methods.
3) Need a multidimensional Array or List.
My current solution is to long winded and due to the large amount of Data the Core site uses, It's response is descending for every feature being added.
Could anyone reference any infrastructure references or possibly give a walk through on how to actually allocate the properties using this ideology?
Thank-you in advance.
Edit: I mean something like this (PHP):
$example = array (
'location1' => array(
'location_id' => 1
),
'location2' => array(
'location_id' => 2
)
);
Now the data can be handled easier by:
foreach($example as $k=>$v){ // todo: handle }
So here $k becomes your array name (ie it could be, Name, Address) and $v becomes your nested array making data so much easier to handle.
While I strongly disagree with the usage of this pattern, I still think it's valuable to know.
I think you are looking for a Dictionary<TKey, TValue>. It provides a way to map keys of any type to values of any type. For your use case:
IDictionary<string, string> DynamicProperties {get; set;} = new Dictionary<string, string>
{
{ "FirstName", "John" },
{ "LastName", "Doe" }
};
You can then iterate over your "properties" with a loop:
foreach(KeyValuePair pair in DynamicProperties)
{
string key = pair.Key; // "FirstName", "LastName"
string value = pair.Value; // "John", "Doe"
// Use them as you wish.
}
You can have dictionaries of dictionaries too. To match your updated example:
IDictionary<string, IDictionary<string, int>> Example {get; set;} = new Dictionary<string, IDictionary<string, int>>
{
{"location1", new Dictionary<string, int> {{"location_id", 1}}},
{"location2", new Dictionary<string, int> {{"location_id", 2}}}
};
But look at this code - you were looking for simplicity. This is not simple at all, nor is it short, clear, or testable. Having classes and properties is the way to go in C#.
I think the root of the problem here is that you are coding with C#, but thinking with PHP ideas. C# is strongly typed, while PHP is weakly typed, (see this wiki article), and you need to readjust your thinking appropriately.
I suggest to look how ViewBag used in MVC works
here a good link
How ViewBag in ASP.NET MVC works
Related
I need a collection that can store and retrieve objects with multiple, potentially shared tags. I need to be able to store one object with multiple tags, and retrieve all objects that have one or more tags.
My first idea was for the collection to store an array of objects, and a Dictionary<string, Hashset<int>> where the key is the tag and the value is the indexes that tag applies to.
For multiple tags, get the intersection of the index collections
To remove a tag from an object, remove that index from the collection
however, if an object is removed from the collection, all the indexes after that point are now incorrect.
Am I heading in the right direction? Is there an existing implementation of this that I'm unaware of, or a standard approach to collections that would help here?
Given
public class Something
{
public HashSet<string> Tags { get; set; }
}
Usage
var list = new List<Something>
{
new Something()
{
Tags = new HashSet<string>() { "tag1", "tag2" }
},
new Something()
{
Tags = new HashSet<string>() { "tag3", "tag4" }
}
};
var searchList = new List<string> { "tag1", "tag4"};
var result = list.Where(x => x.Tags.Any(y => searchList.Contains(y)));
Fairly standard in memory approach
If you wanted it more typed, use enums (if you don't need them dynamic)
You've headed in the right direction. I would say that you should cache common intersections in other HashSet<T> instances to even speed up and simplifiy things more.
however, if an object is removed from the collection, all the indexes
after that point are now incorrect.
Although you can build an inverse dictionary Dictionary<int, HashSet<string>> in order to remove a given object from the tag index to avoid iterating the entire index when some object is removed:
var tags = objectTagMap[394]
foreach(var tag in tags)
tagObjectMap[tag].Remove(394)
Anyway, if you're thinking about an in-memory index, why don't you use Redis? Redis provides you both hashes (dictionaries), sets and sorted sets (and some other data structures).
This is a very very simplified sample of how you would build the same strategy in Redis:
# Store objects as key-value pairs
set object:1 { "id": 1 }
set object:2 { "id": 2 }
set object:3 { "id": 3 }
// sadd (set add) to build the tag index
sadd tagA 1 2
sadd tagB 3
// sunion to get object ids from two or more tags
sunion tagA tagB
// mget (multiple get) to get object data from the result
// of sunion concatenating "object:" with each object id
// This is a simple example. In a real world system you would use
// SCAN to avoid bottlenecks and being able to leverage paging.
mget object:1 object:2 object:3
Why not use:
Dictionary<List<string>, HashSet<int>> taggedDict = new Dictionary<List<string>, HashSet<int>>();
var searchList = new List<string> { "tag1", "tag4" };
var keys = taggedDict.Keys.Where(x => x.Any(y => searchList.Contains(y)));
This isn't the best way, but the way I'm using for now until it becomes a problem is simply a collection consisting of two dictionaries; Dictionary<string, Hashset<T>> to get objects with a tag, and Dictionary<T, Hashset<string>> to get the tags on an object. It's simple and functional, and should suffice for smaller collections.
I have a dictionary that contains another dictionary as value
something like this
Dictionary<string, Dictionary<double,double>>
now I want to sort it by internal dictionary's value
how can I do that??
From the looks of your comment
sorry i am not expert on c#, would you suggest a way to store 3 values as one item?
I would suggest creating a class and sort on it like this
public class MyClass
{
public string StringProperty {get;set;}
public int FirstDoubleProperty {get;set;}
public int SecondDoubleProperty {get;set;}
}
Then create a collection like this
List<MyClass> MyClasscol = new List<MyClass>();
MyClass mc = new MyClass();
mc.StringProperty = "User1225072";
mc.FirstDoubleProperty = 5;
mc.SecondDoubleProperty = 6;
MyClasscol.Add(mc);
mc = new MyClass();
// and So on
then sort like this
var newsortedcollection = MyClasscol.OrderBy(x => x.FirstDoubleProperty);
Assuming you are now trying to figure out how to store and order a collection of objects with multiple properties, then you have a few options. Nikhil Agrawal's answer is a great solution but there are times when you may not need/want to create a custom class for this. For these situations (preferably when your code is private and not part of some API) then the alternatives below might be an option.
KeyValuePairs
Based on your requirements and your original post using dictionaries, it seems like instead of a dictionary of dictionaries (multi-tiered), you probably wanted a dictionary of keyvaluepairs (flat).
// using keyvaluepair
var keyValueDict = new Dictionary<string, KeyValuePair<double, double>>();
keyValueDict.Add("string", new KeyValuePair<double, double>(5.8, 7.4));
var sortedKeyValues = keyValueDict.OrderBy(x => x.Value.Key);
Tuples
An alternative to the not so pleasant KeyValuePair is the Tuple introduced in .NET 4. The tuple is a generic class which allows you to store typed property values without creating your own custom class. It is worth noting that there are tuple implementations for up to 8 properties.
// using tuple
var tupleList = new List<Tuple<string, double, double>>();
tupleList.Add(new Tuple<string, double, double>("string", 5.8, 7.4));
var sortedTuples = tupleList.OrderBy(x => x.Item2);
There are some good SO questions about Tuples if you are interested:
Is Using .NET 4.0 Tuples in my C# Code a Poor Design Decision?
Are EventArg classes needed now that we have generics
I am parsing a test file, in for form of:
[Person]: [Name]-[John Doe], [Age]-[113], [Favorite Color]-[Red].
[Person]: [Name]-[John Smith], [Age]-[123], [Favorite Color]-[Blue].
[Person]: [Name]-[John Sandles], [Age]-[133], [Favorite Color]-[Green].
[Person]: [Name]-[Joe Blogs], [Age]-[143], [Favorite Color]-[Khaki].
As you can see, the values are not duplicated (though I want to account for future dupes), but the Keys are dupes. The keys being the parts before the hyphen (-).
But everytime I get these into a Dictionary it has a fit and tells me dupes aren't allowed. Why doesn't the Dictionary allow dupes? And how can I overcome this?
The Dictionary has the TKey part of it being hashed for fast lookup, if you have dupes in there, you'll get into collisions and complexities, which will reduce your ability to look things up quickly and efficiently. That is why dupes are not allowed.
You could make a struct with the data in it, and put that in a Dictionnary<ID, MyStruct> for example. This way you avoid dupes in the key (which is unique for each struct, and you have all your data in a Dictionary.
Dictionary can have dupes in value but cannot have dupes in Key because then how will you tell which key's value do you want.
And how can I overcome this
use a KeyvaluePair[] but in that case also how will you tell which key's value do you want?
You can use the Wintellect Power Collections' MultiDictionary class. Power Collections is a long-established set of collection classes for .Net 2 or later. It hasn't been updated for 5 years, but it doesn't need to be.
See here: http://powercollections.codeplex.com/
Download it here: http://powercollections.codeplex.com/releases/view/6863
The simplest thing to do is to use an Dictionary<string, List<string>>.
Usage:
foreach(var person in persons)
{
List<string> list;
if(!dict.TryGetValue(person.Key, out list)
{
list = new List<string>();
dict.Add(person.Key, list);
}
list.Add(person.Data);
}
Lookup<TKey, TElement> class from System.Linq namespace represents a collection of keys each mapped to one or more values. More info: MSDN
List<Person> list= new List<Person>();
// ...
var lookup = list.ToLookup(person => person.Key, person => new {Age=person.Age, Color=person.Color});
IEnumerable<Person> peopleWithKeyX = lookup["X"];
public class Person
{
public string Key { get; set; }
public string Age { get; set; }
public string Color { get; set; }
}
Based on your question I suppose that you are using [Name], [Age] and [Favorite Color] as keys. There are many ways how to put your data into the dictionary using these keys, but the real question is how will you get it back?
The keys in Dictionary should be unique, so you need to find some unique data to use it as a key.
In your case the test file looks like list of Persons, where each line contains person's data. So the most natural way is to compose a dictionary that contains rows about persons where 'unique data' should be a Person's name, unless it is not duplicated.
In real life however Person's name is usually a bad choice, (not only because it may change over time, but also because the probability of identical names is very high), so artificial keys are used instead (row number, Guids, etc.)
Edit I see that number of properties may vary. So you need to use nested dictionaries. Outer - for 'Persons' and inner for Person properties:
Dictionary<string, Dictionary<string, string>> person_property_value;
However for your data structure to be more understandable you should put the inner dictionary inside Person class:
class Person{
public readonly Dictionary<string, string> props;
public Person()
{
props = new Dictionary<string, string>();
}
}
Now you add the Person as:
Person p = new Person();
p.props['Name'] = 'John Doe';
p.props['Age'] = 'age';
dictionary.Add('John Doe', p);
And get it back as:
Person p = dictionary[Name];
Now to allow several persons share the same name you declare the dictionary as Dictionary<string, List<Person>>
I am drawing a blank here.. I am using MVC and my model doesn’t have the Value Name, it just has the ID.
The problem is with ‘itm.DegreeTypeId’ it is just an int. But I need to match it up with a string name.. so DegreeTypeId 1 = Associates Degree, 2 = Bachelor, 3 = MBA etc.
I don’t want to update the model to have the name, but instead to a quick lookup. What’s the best way to proceed here? I know I can create a method and have it return the string based on a number but there has to be a better cleaner way.
string education = string.Empty;
int eduCount = 0;
foreach (var itm in candidate.Educations)
{
if (eduCount > 0) education += "<br><br>";
education += string.Format("<b>{0}</b><br>{1} {2}<br>{3}Graduated: {4}<br>",
itm.DegreeTypeId,
itm.InstitutionName,
itm.InstitutionLocation,
itm.GraduatedOn.HasValue
? string.Format("{0:MMMM yyyy}", itm.GraduatedOn.Value)
: string.Empty);
eduCount++;
}
Try using a Dictionary
static readonly Dictionary<int, string> Degrees = new Dictionary<int, string>() {
{1, "Associates Degree"},
{2, "Bachelor"},
{3, "MBA"},
...
};
So the relevant snippet looks like this:
education += string.Format("<b>{0}</b><br>{1} {2}<br>{3}Graduated: {4}<br>",
Degrees(itm.DegreeTypeId),
...
It's not entirely clear what you're after, but a Dictionary<int, string> could work (or the reverse if you're trying to look things up the other way). Even a string[] could be a simple solution for int to string conversion:
static readonly string[] DegreeTypeNames = { null, // Unused
"Associates Degree",
"Bachelor",
"MBA"
};
That's useful (and performs really well) if you've got a lot of consecutive values, but if they're not all consecutive, the dictionary approach would be better.
If you need to refer to these IDs in code, you should potentially consider using an enum.
I am getting a datatable with customer data from a MySql databaes and a customer object from a web service.
I want to compare every value in the datatable with the values in the object and if there is one field that differs I want to perfrom some tasks.
I know I can get the values from the datatable with:
string mCompanyName = row["Company Name"].ToString();
string mCreatedDate = row["Created Date"].Tostring();
//etc..
Then I get the values from the web service
string wsCompanyName = customer.companyName;
string wsCreatedDate = customer.createdDate;
There are about 50 fields and doing
if( mCompanyName != wsCompanyName & mCreatedDate != wsCreatedDate and so on..) (or similar)
{
//Do something
}
seems to be a bit tedious and not very nice so how should I perform this? Is there a much better way to chuck it into a list and use some fancy LINQ?
Thanks in advance.
For cases like this I sometimes put them ("the objects") in something IEnumerable (make sure to "line them up") and use the SequenceEqual extension method. It performs standard Equals()'ity and is "cheap enough for my usage".
For instance:
var equal = (new object[] { row["A"], row["B"] })
.SequenceEqual(new object[] { x.A, x.B });
This requires LINQ, of course.
I'd put them in a Dictionary and search that way:
Dictionary<string, string> mData = new Dictionary<string, string>();
mData.Add("Company Name", row["Company Name"].ToString());
Dictionary<string, string> wsData = new Dictionary<string, string>();
wsData.Add("Company Name", customer.CompanyName);
Then loop through:
foreach (KeyValuePair<string, string> pair in mData)
{
if (wsData[pair.Key] == pair.Value)
{
// Do something
}
}
This way, for every entry in mData (the data from your database), it will look for an entry in wsData with the same name.
I wouldn't create individual variables for each piece of data. It would be difficult to maintain, and would not scale well (lots of copy and pastes).
I think this might help you, but it needs to modify this to use in your scenerio stackoverflow link