I have objects called Country. At some point in the program, I want to set the field power of each object.
The power for each country is fixed and I have data for all 196 countries here on a piece of paper. My code should check, for instance, if the country's name is USA (and if so, set its power to 100) and so on.
I know I can do it with a switch-case, but what is the best, nicest, and most efficient way to do it?
You can store country-power pairs into a Dictionary<string, int> then just get the score of a particular country by using indexer:
var points = new Dictionary<string,int>();
// populate the dictionary...
var usa = points["USA"];
Edit: As suggested in comments you should store the information in external file, for example an xml would be a good choice. That way you don't have to modify the code to add or remove countries. You just need to store them into XML file, edit it whenever you need.Then parse it when your program starts, and load the values into Dictionary.You can use LINQ to XML for that.If you haven't use it before there are good examples in the documentation to get you started.
Whilst Selmans answer is right and good, it does not answer how to actually populate the Dictionary. Here is it:
var map = new Dictionary<string, int> {
{"USA", 100},
{"Germany", 110}
};
you may however also just add it as follows:
map.Add("USA", 100);
map.Add("Germany", 110);
Now you may access the value (as already mentioned by Semans):
map["USA"] = 50; // set new value for USA
int power = map["USA"]; // get new value
EDIT: As already mentioned within comments and other answers you may of course store the data within an external file or any other data-storage. Having said this you may just initialize an empty dictionary and then fill it with the Add-method previously mentioned for every record within that storage.
This is the right question to begin with, but there are a lot of things you need to learn. Many folk have given you answers to the question you asked. I'm going to be annoyingly Zen and tell you to unask the question because there is a larger problem to resolve.
Instead of hard coding this, store the related properties in an n-tuple also known as a database row and use a database engine to manage the relation between the two. And then since you are using C# it would probably be smart to learn to use LINQ. But before you do that, learn a bit of data modelling theory, because data-modelling is what you are doing.
Since you said you have "objects" called "Country", and you have tagged your question "C#", it would seem that you have two forces at work in your code. One is that having to refer to a map, however efficiently implemented, is not as cheap as referring to a member variable. On the other hand there might be some benefit to a setup where all the attributes of a country can be found in the same place as the attributes of other countries (the map-oriented solutions do address this concern). But these forces can be reconciled something like this:
class Country { // Apologies that this sketch is more C++ than C#
public:
Country(string name_, int power_);
private:
string name;
int power;
};
void MakeCountries()
{
countries.Add(new Country("USA", 50));
countries.Add(new Country("Germany", 60));
// ....
}
Do you need to update your data at runtime?
Yes? Load data from external storage into a dictionary.
No? Use a switch
Let the compiler generate dictionaries and hash-based lookups for you.
When you profiler starts screaming, explore alternative solutions.
For example, read that answer from "What is quicker, switch on string or elseif on type?".
What about making an array of Strings for storing country names in ascending order of their power. It will be more simple to implement.Then the index of each country can represent its power. This is possible, only if the power is continues counting numbers.
If its not , another siple way is to implement them as linked list. So that u will be able to change if u want. A list with 2 fields; 1for the country and other for the power
Related
Ive been struggling to figure out what the correct way to do this is.
I have a table in Excel that relates Motor horsepower size to the amount of space it takes up.
I would like to implement a lookup function of this information in a C# Windows Form that I am writing.
I want to create a function that has a single argument passed to it (double HP). It would lookup if the motor HP falls in-between "Low" and "High" and then it would return the value in the "Space Factor" column. I feel pretty silly for not knowing the best way to do this. I want to avoid IF/Else statements as it doesnt seem like the right approach. Additionally, interfacing with Excel to do the lookup also seems a little silly.
How would you interface with a data table like this?
You should create an class to represent your rows, you can then add each object to a list. If you have few items you can just use Linq:
var hp = 20;
var objects = new List<MyClass>(){...};
var foundObj = objects.FirstOrDefault(o => hp > o.HpLow && hp < o.HpHigh);
if(foundObj != null){
// Found object!
}
If you have lots of rows you can instead sort the list by the HpHigh, and use BinarySearch to find the item without iterating over all items, but it requires a custom comparer and is a bit more complex.
If hp-ranges can overlap for you need some way to determine which of the rows is the most fitting one, so I'm just going to assume ranges do not overlap.
I would personally do this with c# arrays, however it might not be best or most practical solution for your solution, which im not quite sure how it works, however array is quick and easy to setup.
i'm currently working on an experimental setup, that is used to write complex microstructures into glass with a femtosecond laser.
The output power of the laser is regulated by a filterwheel which i control from my (C# console)application. As I initially do not know the position of the wheel, I need to initalize it on startup, by measuring the power for a predefined number of points on the wheel.
This information (power values and their corresponding position on the wheel) should be stored during runtime. So basically if a certain output power is requested, the controller will look up the two points in between which the desired value can be found and then increments the position until it is reached.
This is something i would usually achieve using a database. As the initialization takes place on every startup and it does not need to be persisted, i would probably prefer to just keep it as an in-memory list.
So my question is:
Is it possible to somehow "index" the power values to retrieve them quickly?
A Dictionary<int, int> would probably be your best bet. Of course, you could switch out the key/value types to match your data if it isn't ints.
You may look at using a SortedDictionary<int, int> if you're going to have to calculate "in-between" values for keys.
Look at the similar question here for an example on finding points between two keys using a SortedDictionary
Some time ago I wrote a small post on the different list types in dotnet with pros and cons.
http://www.selfelected.com/list-of-list-and-collection-classes-in-dotnet-11-45/
if you want to map each key to a value you should use Dictionary<key,value>
Not long ago I posted a question about a design decision of my F1 game. One person replying noted my use of Dictionary<int, Driver> and asked what it was for. I use this collection for having a finish position and a Driver at that finish position. He suggested I should use arrays, because arrays have a index that could be used as position.
Having not worked on the game for a while, I picked up where I left and started to think about replacing my Dictionaries with arrays. I started googling arrays and one thing let to another and I came across posts here on SO, some blogs (http://blogs.msdn.com/b/ericlippert/archive/2008/09/22/arrays-considered-somewhat-harmful.aspx) about not to use arrays (or, actually, in some very specific cases).
My questions are these:
When data comes from the database, and is only used for comparing and looking up data, what is best used? I have a
prediction, which contains drivers and a predicted finish position
result, which also contains drivers and a finish position
points, which contains the points for every correctly guessed Driver at a certain finish position
The data comes from the database, and shouldn't be edited, added to, or removed.
The data is only used by my code only, but does that mean that I can safely use a collection, or should I really be on the safe side anyway and make sure that what comes back from the database is an immutable collection?
And the second question has to do with the positions. What collection can I use so that I can have finish positions, without maybe the overhead of using a Dictionary?
var prediction = new Driver[3];
prediction[0] = new Driver(10, "Michael Schumacher");
prediction[1] = new Driver(7, "Felipe Massa");
prediction[2] = new Driver(8, "Jensen Button");
var results = new Driver[3];
results[0] = new Driver(10, "Michael Schumacher");
results[1] = new Driver(8, "Jensen Button");
results[2] = new Driver(9, "Fernando Alonso");
int[] points = { 25, 18, 15, 12, 10 };
for (int i = 0; i < prediction.Length; i++)
{
if (prediction[i].Equals(results[i]))
{
result += points[i];
}
}
It depends on if you want to check by position (e.g. "Who finished third?") or by driver (e.g. "What position did Wilson finish at?"). It also depends on whether you care that much about performance in a scenario which sounds like it won't really make a difference to your application as a whole.
Generally a dictionary would be good for lookups. However, if the range of the keys is known, small, and continuous ("race position" fits all three criteria) then a dictionary does not offer anything more than an array (and has more overhead). So if you want to query by position, use an array because it's the simplest tool that fits the job description.
If you want to query by driver, then first you have to answer the question "how exactly is the identity of a Driver defined?" (an answer might be "each driver is uniquely identified by their last name, first name and date of birth").
You could then make the Driver class implement IEquatable<Driver> using these criteria and put it in a Dictionary<Driver, Positions> where I am using the class below to avoid multiple dictionaries.
class Positions
{
public int Predicted { get; set; }
public int Actual { get; set; }
}
However, you have to ask yourself if going to all this trouble makes any sense vs. having an array of e.g. Tuple<Driver, Positions> and looping over the array to find the driver you want each time. This may sound inefficient in theory, but if you have just 20 drivers it will actually be much faster than a dictionary.
Finally, I don't see any need in going out of your way to mark these data structures as immutable and/or enforce immutability. Since your application works in read-only mode, and it does not include code that attempts to push data back to the database, I think it's pretty clear that it's meaningless to go around modifying the data in code.
I use this collection for having a finish position and a Driver at
that finish position. He suggested I should use arrays, because arrays
have a index that could be used as position.
And for that case, he's pretty much right. An array is really the best way to do that because you know how many positions there are and the index acts as the position. It's going to use the least memory and get the most performance, and it's simple. I mean you could also use a List, which for this purpose is really just a fancier array.
There might be cases where arrays are "harmful", but there's also a case to be made that you should stick to simple tools when that's all you need to do the job. Arrays are simple, easily understood, and fast. When all you need is a Driver and a finish position, an Array is a perfect tool.
When data comes from the database, and is only used for comparing and
looking up data, what is best used? I have a
prediction, which contains drivers and a predicted finish position result, which also contains drivers and a finish position points,
which contains the points for every correctly guessed Driver at a
certain finish position
That depends. Do you want one collection that stores all of that information? If you do, Jon's suggestion of a Dictionary is probably your best bet. I suspect that's going to be a good way to go because it's got everything you need in a single place that you can work with.
If instead you want a different collection for each one, then for results and predicted results you can just use an Array for each one (as the data is perfectly suited for it). For points it's a bit different because the points aren't likely to be a perfectly set of index values and you could have two results with the same score.
I am writing an in-house application that holds several pieces of text information as well as a number of pieces of data about these pieces of text. These pieces of data will be held within a database (SQL Server, although this could change) in order of entry.
I'd like to be able to search for the most relevant of these pieces of information, with the most relevant of these to be at the top. I originally looked into using SQL Server Full-Text Search but it's not as flexible for my other needs as I had hoped so it seems that I'll need to develop my own solution to this.
From what I understand what is needed is an inverted index, then for the contents of said inverted index to be restored and modified based on the results of the additional information held (although for now this can be left for a later date as I just want the inverted index to index the main text from the database table/strings provided).
I've had a crack at writing this code in Java using a Hashtable with the key as the words and the value as a list of the occurrences of the word but in all honesty I'm still rather new at C# and have only really used things like DataSets and DataTables when handling information. If requested I'll upload the Java code soon once I've cleared this laptop of viruses.
If given a set of entries from a table or from a List of Strings, how could one create an inverted index in C# that will preferably save into a DataSet/DataTable?
EDIT: I forgot to mention that I have already tried Lucene and Nutch, but require my own solution as modifying Lucene to meet my needs would take far longer than writing an inverted index. I'll be handling a lot of meta-data that'll also need handling once the basic inverted index is completed, so all I require for now is a basic full-text search on one area using the inverted index. Finally, working on an inverted index isn't something I get to do every day so it'd be great to have a crack at it.
Here's a rough overview of an approach I've used successfully in C# in the past:
struct WordInfo
{
public int position;
public int fieldID;
}
Dictionary<string,List<WordInfo>> invertedIndex=new Dictionary<string,List<WordInfo>>();
public void BuildIndex()
{
foreach (int fieldID in GetDatabaseFieldIDS())
{
string textField=GetDatabaseTextFieldForID(fieldID);
string word;
int position=0;
while(GetNextWord(textField,out word,ref position)==true)
{
WordInfo wi=new WordInfo();
if (invertedIndex.TryGetValue(word,out wi)==false)
{
invertedIndex.Add(word,new List<WordInfo>());
}
wi.Position=position;
wi.fieldID=fieldID;
invertedIndex[word].Add(wi);
}
}
}
Notes:
GetNextWord() iterates through the field and returns the next word and position. To implement it look at using string.IndexOf() and char character type checking methods (IsAlpha etc).
GetDatabaseTextFieldForID() and GetDatabaseFieldIDS() are self explanatory, implement as required.
Lucene.net might be your best bet. Its a mature full text search engine using inverted indexes.
http://codeclimber.net.nz/archive/2009/09/02/lucene.net-your-first-application.aspx
UPDATE:
I wrote a little library for indexing against in-memory collections using Lucene.net - it might be useful for this. https://github.com/mcintyre321/Linqdex
If you're looking to spin your own, the Dictionary<T> class is most likely going to be your base, like your Java hashtables. As far as what is stored as the values in the dictionary, its hard to tell based on the information you provide, but typically search algorithms use some type of Set structure so you can run unions and intersections. LINQ gives you a much of that functionality on any IEnumerable, although a specialized Set class may boost performance.
One such implementation of a Set is in the Wintellect PowerCollections. I'm not sure if that would give you any performance benefit or not over LINQ.
As far as saving to a DataSet, I'm not sure what you're envisioning. I'm not aware of anything that "automagically" writes to a DataSet. I suspect you will have to write this yourself, especially since you mentioned several times about other third-party options not being flexible enough.
I have a question about this question. I posted a reply there but since it's been marked as answered, I don't think I'll get a response to my post there.
I am running C# framework 2.0 and I
would like to get some of the data
from a list? The list is a List<>. How
can I do that without looping and
doing comparaison manually on each
element of the List<>?
It really looks like the answers are just a more elegant ways of comparing every element of the List. Given that the list is not guaranteed to be sorted prior to the search, do any of the methods provided in the original post ensure that they are looking at a smaller subset of the original list?
EDIT: One thing to note is that I'm not trying to do anything here. I just want to know if the solutions provided in another question truly do what the OP asked, with regards to looping through the whole list. In general, to search an unsorted list (at least it's not required given the data structure), you will have to search the entire list. However, do any of the solutions on the other thread have an underlying optimization to prevent searching the entire list?
EDIT: I really didn't get any answers that were all that helpful but I will give credit to the answer that at least confirmed my common sense belief. If I notice a new answer that is better, I will change my vote.
If your requirement is to find things quickly in an arbitrary collection, then perhaps a list isn't the best data structure for the job. :)
You might want to check out LINQ support for .Net 2.0.
Has explain in the thread your mentionned you can get some of the object from the list without LINQ.
list = list.FindAll(yourFilterCriteria);
The object yourFilterCriteria is a Predicate and can do comparison with all Property or Function in your object so it's very customizable.
Predicate<SimpleObject> yourFilterCriteria = delegate(SimpleObject simpleObject)
{
return simpleObject.FirstName.Contains("Skeet") && simpleObject.Age < 30;
};
This example show you that you can search the list without looping manullay and you will get all people with the First Name Skeet and Age under 30.
If you're only looking for the first match, then the Find method will do the job. It won't loop through the entire list, rather it will return the first occurrence of the object. However, if you want to find all of them, how exactly do you expect to search through only a subset of the data if it isn't sorted?