I need to represent a lookup table in C#, here is the basic structure:
Name Range Multiplier
Active 10-20 0.5
What do you guys suggest?
I will need to lookup on range and retrieve the multiplier.
I will also need to lookup using the name.
UPdate
It will have maybe 10-15 rows in total.
Range is integer date type.
What you actually have is two lookup tables: one by Name and one by Range. There are several ways you can represent these in memory depending on how big the table will get.
The mostly-likely fit for the "by-name" lookup is a dictionary:
var MultiplierByName = new Dictionary<string, double>() { {"Active",.5}, {"Other", 1.0} };
The range is trickier. For that you will probably want to store either just the minimum or the maximum item, depending on how your range works. You may also need to write a function to reduce any given integer to it's corresponding stored key value (hint: use integer division or the mod operator).
From there you can choose another dictionary (Dictionary<int, double>), or if it works out right you could make your reduce function return a sequential int and use a List<double> so that your 'key' just becomes an index.
But like I said: to know for sure what's best we really need to know the scope and nature of the data in the lookup, and the scenario you'll use to access it.
Create a class to represent each row. It would have Name, RangeLow, RangeHigh and Multiplier properties. Create a list of such rows (read from a file or entered in the code), and then use LINQ to query it:
from r in LookupTable
where r.RangeLow <= x && r.RangeHigh >= x
select r.Multiplier;
Sometimes simplicity is best. How many entries are we looking at, and are the ranges integer ranges as you seem to imply in your example? While there are several approaches I can think of, the first one that comes to mind is to maintain two different lookup dictionaries, one for the name and one for the value (range) and then just store redundant info in the range dictionary. Of course, if your range is keyed by doubles, or your range goes into the tens of thousands I'd look for something different, but simplicity rules in my book.
I would implement this using a DataTable, assuming there was no pressing reason to use another datatype. DataTable.Select would work fine for running a lookup on Name or Range. You do lose some performance using a DataTable for this but with 10-15 records would it matter that much.
Related
I have a table that has Constant Value...Is it better that I have this table in my Database(that is SQL)or have an Enum in my code and delete my table?
my table has only 2 Columns and maximum 20 rows that these rows are fixed and get filled once,first time that i run application.
I would suggest to create an Enum for your case. Since the values are fixed(and I am assuming that the table is not going to change very often) you can use Enum. Creating a table in database will require an unnecessary hit to the database and will require a database connection which could be skipped if you are using Enum.
Also a lot may depend on how much operation you are going to do with your values. For example: its tedious to query your Enum values to get distinct values from your table. Whereas if you will use table approach then it would be a simple select distinct. So you may have to look into your need and the operations which you will perform on these values.
As far as the performance is concerned you can look at: Enum Fields VS Varchar VS Int + Joined table: What is Faster?
As you can see, ENUM and VARCHAR results are almost the same, but join
query performance is 30% lower. Also note the times themselves –
traversing about same amount of rows full table scan performs about 25
times better than accessing rows via index (for the case when data
fits in memory!)
So, if you have an application and you need to have some table field
with a small set of possible values, I’d still suggest you to use
ENUM, but now we can see that performance hit may not be as large as
you expect. Though again a lot depends on your data and queries.
That depends on your needs.
You may want to translate the Enum Values (if you are showing it in GUI) and order a set of record based on translated values. For example: imagine you have a Employees table and a Position column. If the record set is big, and you want to sort or order by translated position column, then you have to keep the enum values + translations in database.
Otherwise KISS and have it in code. You will spare time on asking database for values.
I depends on character of that constants.
If they are some low level system constants that never should be change (like pi=3.1415) then it is better to keep them only in code part in some config file. And also if performance is critical parameter and you use them very often (on almost each request) it is better to keep them in code part.
If they are some constants (may be business constants) that can change in future it is Ok to put them in table - then you have more flexibility to change them (for instance from admin panel).
It really depends on what you actually need.
With Enum
It is faster to access
Bound to that certain application. (although you can share by making it as reference, but it just does not look as good as using DB)
You can use in switch statement
Enum usually does not care about value and it is limited to int.
With DB
It is slower, because you have to make connection and query.
The data can be shared widely.
You can set the value to be anything (any type any value).
So, if you will use it only on certain application, Enum is good enough. But if several applications are going to use it, then DB would be better option.
I have a list of Numbers that are linked to each other:
000-1100-00
001-1100-00
000-1205-01
001-1205-01
001-1205-00
and so forth..
I need a data structure or a way to be able to apply filters on the above.
For example, if the second set of number has to be filtered on 1205, then the numbers will come back as
001-1205-01
000-1205-01
001-1205-00
A secondary filter might then be applied after the first one and if I filter on the third set of number, 01, then the number returned will be:
001-1205-01
000-1205-01
Now, there might be an N number of sets so it's not only three sets. However, all numbers will have the same amount of Sets, so if the number of sets is four, the it will end up looking something like:
123-11-22-54
What options are available to me?
If I add the above as columns to a SQL database, how can I do searches without using Dynamic SQL to create filters?
If not through SQL, is there an alternative with C# and its data structures?
You don't need dynamic SQL, but you do need to know what you are looking for. If you want 1205 in the second position of 3, then use:
where numbers like '%-1205-%'
for the third set use either:
where numbers like '%-1205-%' and numbers like '%-01'
or
where numbers like '%-1205-01'
This about constructing the right parameter for comparison, not dynamic SQL.
In any case, the full answer to your question is likely to be regular expressions. However, the implementation of these is quite database-specific and you don't mention what database you are using.
To elaborate on what I'm asking here, I'm working in C# trying to order a list of data that is coming out of a database. A certain object (table) has two separate properties (columns) which can hold dates. I want to sort this list based on date, meaning for each data row, I want to take the maximum of the two dates and use that for the sort.
Is there an elegant way to do this? At the moment I'm thinking that I should just get the max time from each record, and store it as a key in a Dictionary, with the data row being the value, and then iterate through the Dictionary with the sorted keys. Although this wouldn't be terrible to code, I'm trying to see if there is a nicer way to do this using Linq. Any help would be appreciated. Thanks.
If you want an alternative for sorting your collection everytime, .NET contains a class called SortedList. Here is the link to the MSDN article: http://msdn.microsoft.com/en-us/library/system.collections.sortedlist(v=vs.110).aspx
MSDN states that a SortedList:
Represents a collection of key/value pairs that are sorted by the keys and are accessible by key and by index.
So if you want to sort by date you can declare your sorted list as:
SortedList<DateTime, YourData> mySortedList = new SortedList<DateTime, YourData>();
and when you add values to it, it will already be sorted. Or you can just go with LINQ and #Alexander answer.
Edit
I just understood what you want to do. You can do:
table.OrderBy(item => Math.Max(item.Date1.Ticks, item.Date2.Ticks));
Note: The linq query above will not be performant on a large collection.
I am wondering which method is the best way to store a list of integers in a sql column.
.....i.e. "1,2,3,4,6,7"
EDIT: These values represent other IDs in SQL tables. The row would look like
[1] [2]
id, listOfOtherIDs
The choices I have researched so far are:
A varchar of separated value that are "explode-able" i.e. by commas or tabs
An XML containing all the values individually
Using individual rows for each value.
Which method is the best method to use?
Thanks,
Ian
A single element of a record can only refer to one value; it's a basic database design principle.
You will have to change the database's design: use a single row for each value.
You might want to read up on normalization.
As is shown here in the description of the first normal form:
First normal form states that at every row and column intersection in the table there, exists a single value, and never a list of values. For example, you cannot have a field named Price in which you place more than one Price. If you think of each intersection of rows and columns as a cell, each cell can hold only one value.
While Jeroen's answer is valid for "multi-valued" attributes, there are genuine situations where multiple comma-separated values may actually be representing one large value. Things like path data (on a map), integer sequence, list of prime factors and many more could well be stored in a comma-separated varchar. I think it is better to explain what exactly are you storing and how do you need to retrieve and use that value.
EDIT:
Looking at your edit, if by IDs you mean PK of another table, then this sounds like a genuine M-N relation between this table and the one whose IDs you're storing. This stuff should really be stored in a separate gerund, which BTW is a table that would have the PK of each of these tables as FKs, thus linking the related rows of both tables. So Jeroen's answer very well suits your situation.
I have a function that receives three different "people" objects and generates a new "compatibility" object based on the combined values in the "people" objects.
However, about 1/3 of the time the three "people" objects that it receives as input are the same as one before, though possibly in a different order. In these cases I do NOT want to make a new "score" object, but simply return a value contained within the existing object.
Originally, the program just loops through the list<> of "compatibility" objects searching for the one that belongs to these three "people" (since each "compatibility" object contains an array of people objects). This method is really slow considering that there's over thousands of "compatibility" objects and over a million "people" objects.
I had the idea of using a dictionary where the key is a number I generated by combining the three people objects' id values into a single UInt64 using XOR, and storing the score objects in as dictionary values rather than in a list. This cuts down the time by about half, and is acceptable in terms of time performance, but there's way too many collisions, and it returns a wrong score too often.
Any suggestions or pointers would be much appreciated.
Edit: To add to the original question, each "people" object has a bunch of other fields that I could use, but the problem is making a key that is UNIQUE and COMMUTATIVE.
I think you're looking at things in a much too complex manner. Take the 3 PersonID values and sort them,so that they're always in the same order, no matter which order they were passed in. Then set a value in a hashtable using the three PersonIDs as the key, separated with a hyphen or some other character that won't occur in a PersonID value. Then later, check if there's a value in the hashtable with that key.
So if the three PersonIDs are 10, 5 and 22, the hash key could be something like "5-10-22".
Create the key by concatinating objectids after sorting the trio in a pre-determined order.
Your best option would be a custom IEqualityComparer class. Declare your Dictionary like this
Dictionary<List<People>, Compatability> people =
new Dictionary<List<People>, Compatability>(new PersonListComparer());
You'll need to create a PersonListComparer class that implements IEqualityComparer<List<People>>. There are two methods you'll need to implement, one that gets a hash code and one that compares equality. The Dictionary will use GetHashCode to determine if two lists are POSSIBLY equal, and the Equals method to determine if they actually are (in other words, the hash code is fast but could give a false positive but never a false negative). Use your existing hashing algorithm (the XOR) for GetHashCode, then just comare the two lists explicitly in the Equals method.
This should do the trick!
Why not use the names of the people as the dictionary key? (Sort the names first, so that order of passing doesn't matter.)
IE, John, Alice, and Bob become something like my_dictionary["Alice_Bob_John"] <- if that key exists, you've already computed the score, otherwise, you need to compute it. As an alternative to my string hacking above, you could actually use a structure:
NameTriple n = new NameTriple("John", "Alice", "Bob");
// NameTriple internally sorts the names.
my_dictionary[n] ...
If you want to keep everything in memory and not use a database, I'd recommend something akin to a tree structure. Assuming your object IDs are sortable and order doesn't matter, you can accomplish this with nested dictionaries.
Namely, a Dictionary<Key, Dictionary<Key, Dictionary<Key, Compatibility>>> should do the trick. Sort the IDs, and use the lowest value in the outer dictionary, the next value in the next, and the final value to find the compatibility object. This way, there will be no collisions, and lookup should be quite fast.
Or, now that I think again, this doesn't have to be that complicated. Just use a string as a key and concatenate the IDs together in sorted order with a "!" or something else in between that doesn't occur naturally in the IDs.
assuming all "Person" objects are unique, store a UUID in the object.
in your function staticly store the quad (P1,P2,P3,V) where P1,P2,P3 are UUID's of a Person object, sorted (to avoid the ordering problem) and V is the result from the previous calculation.
then your function checks to is if there is an entry for this triplet of Persons, if not it does the work and stores it.
you can store the (P1,P2,P3,V) values in a dictionary, just key off some hash of the three P values